blob: 2ec01ded987f69bf034db0847bb8d67776020cbd [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, 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"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080081#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080082
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053083#ifdef DYNAMIC_LOG_ENABLED
84#include <log_xml_parser.h>
85#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
86#include <log_utils.h>
87#endif
88
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053090/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
91#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070093#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070094#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053095#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053096#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070097#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070098#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070099
Aalique Grahame22e49102018-12-18 14:23:57 -0800100#define RECORD_GAIN_MIN 0.0f
101#define RECORD_GAIN_MAX 1.0f
102#define RECORD_VOLUME_CTL_MAX 0x2000
103
104/* treat as unsigned Q1.13 */
105#define APP_TYPE_GAIN_DEFAULT 0x2000
106
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700107#define PROXY_OPEN_RETRY_COUNT 100
108#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800109
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800110#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
111 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
112 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
113#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
114 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800115
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700116#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700117#define DEFAULT_VOIP_BUF_DURATION_MS 20
118#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
119#define DEFAULT_VOIP_SAMP_RATE 48000
120
121#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
122
123struct pcm_config default_pcm_config_voip_copp = {
124 .channels = 1,
125 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
126 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
127 .period_count = 2,
128 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800129 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
130 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700131};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700132
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700133#define MIN_CHANNEL_COUNT 1
134#define DEFAULT_CHANNEL_COUNT 2
135#define MAX_HIFI_CHANNEL_COUNT 8
136
Aalique Grahame22e49102018-12-18 14:23:57 -0800137#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
138#define MAX_CHANNEL_COUNT 1
139#else
140#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
141#define XSTR(x) STR(x)
142#define STR(x) #x
143#endif
144
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700145static unsigned int configured_low_latency_capture_period_size =
146 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
147
Haynes Mathew George16081042017-05-31 17:16:49 -0700148#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
149#define MMAP_PERIOD_COUNT_MIN 32
150#define MMAP_PERIOD_COUNT_MAX 512
151#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
152
Aalique Grahame22e49102018-12-18 14:23:57 -0800153/* This constant enables extended precision handling.
154 * TODO The flag is off until more testing is done.
155 */
156static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700157extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800158
Eric Laurentb23d5282013-05-14 15:27:20 -0700159struct pcm_config pcm_config_deep_buffer = {
160 .channels = 2,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
163 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
166 .stop_threshold = INT_MAX,
167 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
168};
169
170struct pcm_config pcm_config_low_latency = {
171 .channels = 2,
172 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
173 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
174 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
175 .format = PCM_FORMAT_S16_LE,
176 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
177 .stop_threshold = INT_MAX,
178 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
179};
180
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800181struct pcm_config pcm_config_haptics_audio = {
182 .channels = 1,
183 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
184 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
185 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
187 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
188 .stop_threshold = INT_MAX,
189 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
190};
191
192struct pcm_config pcm_config_haptics = {
193 .channels = 1,
194 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
195 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
196 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
197 .format = PCM_FORMAT_S16_LE,
198 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
199 .stop_threshold = INT_MAX,
200 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
201};
202
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700203static int af_period_multiplier = 4;
204struct pcm_config pcm_config_rt = {
205 .channels = 2,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = ULL_PERIOD_SIZE, //1 ms
208 .period_count = 512, //=> buffer size is 512ms
209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = ULL_PERIOD_SIZE, //1 ms
215};
216
Eric Laurentb23d5282013-05-14 15:27:20 -0700217struct pcm_config pcm_config_hdmi_multi = {
218 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
219 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
220 .period_size = HDMI_MULTI_PERIOD_SIZE,
221 .period_count = HDMI_MULTI_PERIOD_COUNT,
222 .format = PCM_FORMAT_S16_LE,
223 .start_threshold = 0,
224 .stop_threshold = INT_MAX,
225 .avail_min = 0,
226};
227
Haynes Mathew George16081042017-05-31 17:16:49 -0700228struct pcm_config pcm_config_mmap_playback = {
229 .channels = 2,
230 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
231 .period_size = MMAP_PERIOD_SIZE,
232 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
233 .format = PCM_FORMAT_S16_LE,
234 .start_threshold = MMAP_PERIOD_SIZE*8,
235 .stop_threshold = INT32_MAX,
236 .silence_threshold = 0,
237 .silence_size = 0,
238 .avail_min = MMAP_PERIOD_SIZE, //1 ms
239};
240
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700241struct pcm_config pcm_config_hifi = {
242 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
243 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
244 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
245 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
246 .format = PCM_FORMAT_S24_3LE,
247 .start_threshold = 0,
248 .stop_threshold = INT_MAX,
249 .avail_min = 0,
250};
251
Eric Laurentb23d5282013-05-14 15:27:20 -0700252struct pcm_config pcm_config_audio_capture = {
253 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700254 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
255 .format = PCM_FORMAT_S16_LE,
256};
257
Haynes Mathew George16081042017-05-31 17:16:49 -0700258struct pcm_config pcm_config_mmap_capture = {
259 .channels = 2,
260 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
261 .period_size = MMAP_PERIOD_SIZE,
262 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
263 .format = PCM_FORMAT_S16_LE,
264 .start_threshold = 0,
265 .stop_threshold = INT_MAX,
266 .silence_threshold = 0,
267 .silence_size = 0,
268 .avail_min = MMAP_PERIOD_SIZE, //1 ms
269};
270
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700271#define AFE_PROXY_CHANNEL_COUNT 2
272#define AFE_PROXY_SAMPLING_RATE 48000
273
274#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
275#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
276
277struct pcm_config pcm_config_afe_proxy_playback = {
278 .channels = AFE_PROXY_CHANNEL_COUNT,
279 .rate = AFE_PROXY_SAMPLING_RATE,
280 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
281 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
282 .format = PCM_FORMAT_S16_LE,
283 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
284 .stop_threshold = INT_MAX,
285 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286};
287
288#define AFE_PROXY_RECORD_PERIOD_SIZE 768
289#define AFE_PROXY_RECORD_PERIOD_COUNT 4
290
Aalique Grahame22e49102018-12-18 14:23:57 -0800291struct pcm_config pcm_config_audio_capture_rt = {
292 .channels = 2,
293 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
294 .period_size = ULL_PERIOD_SIZE,
295 .period_count = 512,
296 .format = PCM_FORMAT_S16_LE,
297 .start_threshold = 0,
298 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
299 .silence_threshold = 0,
300 .silence_size = 0,
301 .avail_min = ULL_PERIOD_SIZE, //1 ms
302};
303
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700304struct pcm_config pcm_config_afe_proxy_record = {
305 .channels = AFE_PROXY_CHANNEL_COUNT,
306 .rate = AFE_PROXY_SAMPLING_RATE,
307 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
308 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
309 .format = PCM_FORMAT_S16_LE,
310 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
311 .stop_threshold = INT_MAX,
312 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
313};
314
Ashish Jainf1eaa582016-05-23 20:54:24 +0530315#define AUDIO_MAX_PCM_FORMATS 7
316
317const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
318 [AUDIO_FORMAT_DEFAULT] = 0,
319 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
320 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
321 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
322 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
323 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
324 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
325};
326
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800327const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700328 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
329 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800330 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800331 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700332 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
333 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700334 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700335 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700336 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
341 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700344 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
345 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700346 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800347 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700348
Eric Laurentb23d5282013-05-14 15:27:20 -0700349 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700350 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530351 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
352 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
353 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530354 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
355 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700356 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700357 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700358 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700359 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700360
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800361 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800362 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400363 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
364 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700365
Derek Chenf7092792017-05-23 12:23:53 -0400366 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700367 [USECASE_VOICE2_CALL] = "voice2-call",
368 [USECASE_VOLTE_CALL] = "volte-call",
369 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800370 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800371 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
372 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800373 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700374 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
375 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
376 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800377 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
378 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
379 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
380
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700381 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
382 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700383 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
384 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700385
386 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
387 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800388 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530389 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700390
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530391 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530392 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
393 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700394
395 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
396 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530397 /* For Interactive Audio Streams */
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
401 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
402 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
403 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700406
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800407 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
408
Derek Chenf6318be2017-06-12 17:16:24 -0400409 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
410
411 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
412 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
413 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
414 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800415 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700416 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530417 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700418};
419
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700420static const audio_usecase_t offload_usecases[] = {
421 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700422 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
426 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
427 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
428 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700430};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800431
Varun Balaraje49253e2017-07-06 19:48:56 +0530432static const audio_usecase_t interactive_usecases[] = {
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
437 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
438 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
441};
442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443#define STRING_TO_ENUM(string) { #string, string }
444
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800445struct string_to_enum {
446 const char *name;
447 uint32_t value;
448};
449
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700450static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700455 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800456 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700459 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
460 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
461 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
466 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
467 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800470};
471
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700472static const struct string_to_enum formats_name_to_enum_table[] = {
473 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
474 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
475 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700476 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
477 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
478 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700479 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800480 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
481 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700482 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800483};
484
485//list of all supported sample rates by HDMI specification.
486static const int out_hdmi_sample_rates[] = {
487 32000, 44100, 48000, 88200, 96000, 176400, 192000,
488};
489
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700490static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800491 STRING_TO_ENUM(32000),
492 STRING_TO_ENUM(44100),
493 STRING_TO_ENUM(48000),
494 STRING_TO_ENUM(88200),
495 STRING_TO_ENUM(96000),
496 STRING_TO_ENUM(176400),
497 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800498 STRING_TO_ENUM(352800),
499 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700500};
501
Carter Hsu2e429db2019-05-14 18:50:52 +0800502struct in_effect_list {
503 struct listnode list;
504 effect_handle_t handle;
505};
506
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700507static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700508static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700509static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700510//cache last MBDRC cal step level
511static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700512
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530513static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
514static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700515static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800516static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530517static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530518
Derek Chen6f293672019-04-01 01:40:24 -0700519static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
520static void in_snd_mon_cb(void * stream, struct str_parms * parms);
521static void out_snd_mon_cb(void * stream, struct str_parms * parms);
522
Zhou Song331c8e52019-08-26 14:16:12 +0800523static int configure_btsco_sample_rate(snd_device_t snd_device);
524
Vatsal Buchac09ae062018-11-14 13:25:08 +0530525#ifdef AUDIO_FEATURE_ENABLED_GCOV
526extern void __gcov_flush();
527static void enable_gcov()
528{
529 __gcov_flush();
530}
531#else
532static void enable_gcov()
533{
534}
535#endif
536
justinweng20fb6d82019-02-21 18:49:00 -0700537static int in_set_microphone_direction(const struct audio_stream_in *stream,
538 audio_microphone_direction_t dir);
539static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
540
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700541static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
542 int flags __unused)
543{
544 int dir = 0;
545 switch (uc_id) {
546 case USECASE_AUDIO_RECORD_LOW_LATENCY:
547 dir = 1;
548 case USECASE_AUDIO_PLAYBACK_ULL:
549 break;
550 default:
551 return false;
552 }
553
554 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
555 PCM_PLAYBACK : PCM_CAPTURE);
556 if (adev->adm_is_noirq_avail)
557 return adev->adm_is_noirq_avail(adev->adm_data,
558 adev->snd_card, dev_id, dir);
559 return false;
560}
561
562static void register_out_stream(struct stream_out *out)
563{
564 struct audio_device *adev = out->dev;
565 if (is_offload_usecase(out->usecase) ||
566 !adev->adm_register_output_stream)
567 return;
568
569 // register stream first for backward compatibility
570 adev->adm_register_output_stream(adev->adm_data,
571 out->handle,
572 out->flags);
573
574 if (!adev->adm_set_config)
575 return;
576
577 if (out->realtime)
578 adev->adm_set_config(adev->adm_data,
579 out->handle,
580 out->pcm, &out->config);
581}
582
583static void register_in_stream(struct stream_in *in)
584{
585 struct audio_device *adev = in->dev;
586 if (!adev->adm_register_input_stream)
587 return;
588
589 adev->adm_register_input_stream(adev->adm_data,
590 in->capture_handle,
591 in->flags);
592
593 if (!adev->adm_set_config)
594 return;
595
596 if (in->realtime)
597 adev->adm_set_config(adev->adm_data,
598 in->capture_handle,
599 in->pcm,
600 &in->config);
601}
602
603static void request_out_focus(struct stream_out *out, long ns)
604{
605 struct audio_device *adev = out->dev;
606
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700607 if (adev->adm_request_focus_v2)
608 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
609 else if (adev->adm_request_focus)
610 adev->adm_request_focus(adev->adm_data, out->handle);
611}
612
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700613static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700614{
615 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700616 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700617
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700618 if (adev->adm_request_focus_v2_1)
619 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
620 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
622 else if (adev->adm_request_focus)
623 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700624
625 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700626}
627
628static void release_out_focus(struct stream_out *out)
629{
630 struct audio_device *adev = out->dev;
631
632 if (adev->adm_abandon_focus)
633 adev->adm_abandon_focus(adev->adm_data, out->handle);
634}
635
636static void release_in_focus(struct stream_in *in)
637{
638 struct audio_device *adev = in->dev;
639 if (adev->adm_abandon_focus)
640 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
641}
642
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530643static int parse_snd_card_status(struct str_parms *parms, int *card,
644 card_status_t *status)
645{
646 char value[32]={0};
647 char state[32]={0};
648
649 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
650 if (ret < 0)
651 return -1;
652
653 // sscanf should be okay as value is of max length 32.
654 // same as sizeof state.
655 if (sscanf(value, "%d,%s", card, state) < 2)
656 return -1;
657
658 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
659 CARD_STATUS_OFFLINE;
660 return 0;
661}
662
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700663static inline void adjust_frames_for_device_delay(struct stream_out *out,
664 uint32_t *dsp_frames) {
665 // Adjustment accounts for A2dp encoder latency with offload usecases
666 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800667 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700668 unsigned long offset =
669 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
670 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
671 }
672}
673
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700674static inline bool free_entry(void *key __unused,
675 void *value, void *context __unused)
676{
677 free(value);
678 return true;
679}
680
681static inline void free_map(Hashmap *map)
682{
683 if (map) {
684 hashmapForEach(map, free_entry, (void *) NULL);
685 hashmapFree(map);
686 }
687}
688
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800689static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700690 audio_patch_handle_t patch_handle)
691{
692 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
693 return;
694
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700695 struct audio_patch_info *p_info =
696 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
697 if (p_info) {
698 ALOGV("%s: Remove patch %d", __func__, patch_handle);
699 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
700 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700701 free(p_info);
702 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700703}
704
705static inline int io_streams_map_insert(struct audio_device *adev,
706 struct audio_stream *stream,
707 audio_io_handle_t handle,
708 audio_patch_handle_t patch_handle)
709{
710 struct audio_stream_info *s_info =
711 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
712
713 if (s_info == NULL) {
714 ALOGE("%s: Could not allocate stream info", __func__);
715 return -ENOMEM;
716 }
717 s_info->stream = stream;
718 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700719
720 pthread_mutex_lock(&adev->lock);
721 struct audio_stream_info *stream_info =
722 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700723 if (stream_info != NULL)
724 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800725 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700726 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
727 return 0;
728}
729
730static inline void io_streams_map_remove(struct audio_device *adev,
731 audio_io_handle_t handle)
732{
733 pthread_mutex_lock(&adev->lock);
734 struct audio_stream_info *s_info =
735 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700736 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800737 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700738 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800739 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700740 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800741done:
742 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 return;
744}
745
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800746static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 audio_patch_handle_t handle)
748{
749 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700750 p_info = (struct audio_patch_info *)
751 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700752 return p_info;
753}
754
vivek mehtaa76401a2015-04-24 14:12:15 -0700755__attribute__ ((visibility ("default")))
756bool audio_hw_send_gain_dep_calibration(int level) {
757 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700758 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700759
760 pthread_mutex_lock(&adev_init_lock);
761
762 if (adev != NULL && adev->platform != NULL) {
763 pthread_mutex_lock(&adev->lock);
764 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700765
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530766 // cache level info for any of the use case which
767 // was not started.
768 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700769
vivek mehtaa76401a2015-04-24 14:12:15 -0700770 pthread_mutex_unlock(&adev->lock);
771 } else {
772 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
773 }
774
775 pthread_mutex_unlock(&adev_init_lock);
776
777 return ret_val;
778}
779
Ashish Jain5106d362016-05-11 19:23:33 +0530780static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
781{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800782 bool gapless_enabled = false;
783 const char *mixer_ctl_name = "Compress Gapless Playback";
784 struct mixer_ctl *ctl;
785
786 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700787 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530788
789 /*Disable gapless if its AV playback*/
790 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800791
792 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
793 if (!ctl) {
794 ALOGE("%s: Could not get ctl for mixer cmd - %s",
795 __func__, mixer_ctl_name);
796 return -EINVAL;
797 }
798
799 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
800 ALOGE("%s: Could not set gapless mode %d",
801 __func__, gapless_enabled);
802 return -EINVAL;
803 }
804 return 0;
805}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700806
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700807__attribute__ ((visibility ("default")))
808int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
809 int table_size) {
810 int ret_val = 0;
811 ALOGV("%s: enter ... ", __func__);
812
813 pthread_mutex_lock(&adev_init_lock);
814 if (adev == NULL) {
815 ALOGW("%s: adev is NULL .... ", __func__);
816 goto done;
817 }
818
819 pthread_mutex_lock(&adev->lock);
820 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
821 pthread_mutex_unlock(&adev->lock);
822done:
823 pthread_mutex_unlock(&adev_init_lock);
824 ALOGV("%s: exit ... ", __func__);
825 return ret_val;
826}
827
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800828bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800829{
830 bool ret = false;
831 ALOGV("%s: enter ...", __func__);
832
833 pthread_mutex_lock(&adev_init_lock);
834
835 if (adev != NULL && adev->platform != NULL) {
836 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800837 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800838 pthread_mutex_unlock(&adev->lock);
839 }
840
841 pthread_mutex_unlock(&adev_init_lock);
842
843 ALOGV("%s: exit with ret %d", __func__, ret);
844 return ret;
845}
Aalique Grahame22e49102018-12-18 14:23:57 -0800846
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700847static bool is_supported_format(audio_format_t format)
848{
Eric Laurent86e17132013-09-12 17:49:30 -0700849 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530850 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530851 format == AUDIO_FORMAT_AAC_LC ||
852 format == AUDIO_FORMAT_AAC_HE_V1 ||
853 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530854 format == AUDIO_FORMAT_AAC_ADTS_LC ||
855 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
856 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530857 format == AUDIO_FORMAT_AAC_LATM_LC ||
858 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
859 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530860 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
861 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530862 format == AUDIO_FORMAT_PCM_FLOAT ||
863 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700864 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530865 format == AUDIO_FORMAT_AC3 ||
866 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700867 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530868 format == AUDIO_FORMAT_DTS ||
869 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800870 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530871 format == AUDIO_FORMAT_ALAC ||
872 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530873 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530874 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800875 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530876 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700877 format == AUDIO_FORMAT_APTX ||
878 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800879 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700880
881 return false;
882}
883
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700884static inline bool is_mmap_usecase(audio_usecase_t uc_id)
885{
886 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800887 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700888 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
889}
890
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700891static inline bool is_valid_volume(float left, float right)
892{
893 return ((left >= 0.0f && right >= 0.0f) ? true : false);
894}
895
Avinash Vaish71a8b972014-07-24 15:36:33 +0530896static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
897 struct audio_usecase *uc_info)
898{
899 struct listnode *node;
900 struct audio_usecase *usecase;
901
902 if (uc_info == NULL)
903 return -EINVAL;
904
905 /* Re-route all voice usecases on the shared backend other than the
906 specified usecase to new snd devices */
907 list_for_each(node, &adev->usecase_list) {
908 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800909 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530910 enable_audio_route(adev, usecase);
911 }
912 return 0;
913}
914
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530915static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530916{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530917 ALOGV("%s", __func__);
918 audio_route_apply_and_update_path(adev->audio_route,
919 "asrc-mode");
920 adev->asrc_mode_enabled = true;
921}
922
923static void disable_asrc_mode(struct audio_device *adev)
924{
925 ALOGV("%s", __func__);
926 audio_route_reset_and_update_path(adev->audio_route,
927 "asrc-mode");
928 adev->asrc_mode_enabled = false;
929}
930
931/*
932 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
933 * 44.1 or Native DSD backends are enabled for any of current use case.
934 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
935 * - Disable current mix path use case(Headphone backend) and re-enable it with
936 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
937 * e.g. Naitve DSD or Headphone 44.1 -> + 48
938 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530939static void check_and_set_asrc_mode(struct audio_device *adev,
940 struct audio_usecase *uc_info,
941 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530942{
943 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530944 int i, num_new_devices = 0;
945 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
946 /*
947 *Split snd device for new combo use case
948 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
949 */
950 if (platform_split_snd_device(adev->platform,
951 snd_device,
952 &num_new_devices,
953 split_new_snd_devices) == 0) {
954 for (i = 0; i < num_new_devices; i++)
955 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
956 } else {
957 int new_backend_idx = platform_get_backend_index(snd_device);
958 if (((new_backend_idx == HEADPHONE_BACKEND) ||
959 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
960 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
961 !adev->asrc_mode_enabled) {
962 struct listnode *node = NULL;
963 struct audio_usecase *uc = NULL;
964 struct stream_out *curr_out = NULL;
965 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
966 int i, num_devices, ret = 0;
967 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530968
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530969 list_for_each(node, &adev->usecase_list) {
970 uc = node_to_item(node, struct audio_usecase, list);
971 curr_out = (struct stream_out*) uc->stream.out;
972 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
973 /*
974 *Split snd device for existing combo use case
975 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
976 */
977 ret = platform_split_snd_device(adev->platform,
978 uc->out_snd_device,
979 &num_devices,
980 split_snd_devices);
981 if (ret < 0 || num_devices == 0) {
982 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
983 split_snd_devices[0] = uc->out_snd_device;
984 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800985 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530986 for (i = 0; i < num_devices; i++) {
987 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
988 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
989 if((new_backend_idx == HEADPHONE_BACKEND) &&
990 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
991 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
992 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
993 __func__);
994 enable_asrc_mode(adev);
995 break;
996 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
997 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
998 (usecase_backend_idx == HEADPHONE_BACKEND)) {
999 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
1000 __func__);
1001 disable_audio_route(adev, uc);
1002 disable_snd_device(adev, uc->out_snd_device);
1003 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1004 if (new_backend_idx == DSD_NATIVE_BACKEND)
1005 audio_route_apply_and_update_path(adev->audio_route,
1006 "hph-true-highquality-mode");
1007 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1008 (curr_out->bit_width >= 24))
1009 audio_route_apply_and_update_path(adev->audio_route,
1010 "hph-highquality-mode");
1011 enable_asrc_mode(adev);
1012 enable_snd_device(adev, uc->out_snd_device);
1013 enable_audio_route(adev, uc);
1014 break;
1015 }
1016 }
1017 // reset split devices count
1018 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001019 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301020 if (adev->asrc_mode_enabled)
1021 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301022 }
1023 }
1024 }
1025}
1026
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001027static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1028 struct audio_effect_config effect_config,
1029 unsigned int param_value)
1030{
1031 char mixer_ctl_name[] = "Audio Effect";
1032 struct mixer_ctl *ctl;
1033 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001034 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001035
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001036 if (in == NULL) {
1037 ALOGE("%s: active input stream is NULL", __func__);
1038 return -EINVAL;
1039 }
1040
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001041 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1042 if (!ctl) {
1043 ALOGE("%s: Could not get mixer ctl - %s",
1044 __func__, mixer_ctl_name);
1045 return -EINVAL;
1046 }
1047
1048 set_values[0] = 1; //0:Rx 1:Tx
1049 set_values[1] = in->app_type_cfg.app_type;
1050 set_values[2] = (long)effect_config.module_id;
1051 set_values[3] = (long)effect_config.instance_id;
1052 set_values[4] = (long)effect_config.param_id;
1053 set_values[5] = param_value;
1054
1055 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1056
1057 return 0;
1058
1059}
1060
1061static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1062 int effect_type, unsigned int *param_value)
1063{
1064 int ret = 0;
1065 struct audio_effect_config other_effect_config;
1066 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001067 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001068
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001069 if (in == NULL) {
1070 ALOGE("%s: active input stream is NULL", __func__);
1071 return -EINVAL;
1072 }
1073
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001074 usecase = get_usecase_from_list(adev, in->usecase);
1075 if (!usecase)
1076 return -EINVAL;
1077
1078 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1079 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1080 if (ret < 0) {
1081 ALOGE("%s Failed to get effect params %d", __func__, ret);
1082 return ret;
1083 }
1084
1085 if (module_id == other_effect_config.module_id) {
1086 //Same module id for AEC/NS. Values need to be combined
1087 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1088 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1089 *param_value |= other_effect_config.param_value;
1090 }
1091 }
1092
1093 return ret;
1094}
1095
1096static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301097{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001098 struct audio_effect_config effect_config;
1099 struct audio_usecase *usecase = NULL;
1100 int ret = 0;
1101 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001102 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001103
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001104 if(!voice_extn_is_dynamic_ecns_enabled())
1105 return ENOSYS;
1106
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001107 if (!in) {
1108 ALOGE("%s: Invalid input stream", __func__);
1109 return -EINVAL;
1110 }
1111
1112 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1113
1114 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001115 if (usecase == NULL) {
1116 ALOGE("%s: Could not find the usecase (%d) in the list",
1117 __func__, in->usecase);
1118 return -EINVAL;
1119 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001120
1121 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1122 if (ret < 0) {
1123 ALOGE("%s Failed to get module id %d", __func__, ret);
1124 return ret;
1125 }
1126 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1127 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1128
1129 if(enable)
1130 param_value = effect_config.param_value;
1131
1132 /*Special handling for AEC & NS effects Param values need to be
1133 updated if module ids are same*/
1134
1135 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1136 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1137 if (ret < 0)
1138 return ret;
1139 }
1140
1141 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1142
1143 return ret;
1144}
1145
1146static void check_and_enable_effect(struct audio_device *adev)
1147{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001148 if(!voice_extn_is_dynamic_ecns_enabled())
1149 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001150
Eric Laurent637e2d42018-11-15 12:24:31 -08001151 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001152
Eric Laurent637e2d42018-11-15 12:24:31 -08001153 if (in != NULL && !in->standby) {
1154 if (in->enable_aec)
1155 enable_disable_effect(adev, EFFECT_AEC, true);
1156
1157 if (in->enable_ns &&
1158 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1159 enable_disable_effect(adev, EFFECT_NS, true);
1160 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001161 }
1162}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001163
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001164int pcm_ioctl(struct pcm *pcm, int request, ...)
1165{
1166 va_list ap;
1167 void * arg;
1168 int pcm_fd = *(int*)pcm;
1169
1170 va_start(ap, request);
1171 arg = va_arg(ap, void *);
1172 va_end(ap);
1173
1174 return ioctl(pcm_fd, request, arg);
1175}
1176
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001177int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001178 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001179{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001180 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001181 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301182 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301183 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001184 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301185 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001186
1187 if (usecase == NULL)
1188 return -EINVAL;
1189
1190 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1191
Carter Hsu2e429db2019-05-14 18:50:52 +08001192 if (usecase->type == PCM_CAPTURE) {
1193 struct stream_in *in = usecase->stream.in;
1194 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001195 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001196
1197 if (in) {
1198 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001199 list_init(&out_devices);
1200 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001201 struct listnode *node;
1202 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1203 USECASE_AUDIO_PLAYBACK_VOIP);
1204 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001205 assign_devices(&out_devices,
1206 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001207 } else if (adev->primary_output &&
1208 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001209 assign_devices(&out_devices,
1210 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001211 } else {
1212 list_for_each(node, &adev->usecase_list) {
1213 uinfo = node_to_item(node, struct audio_usecase, list);
1214 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001215 assign_devices(&out_devices,
1216 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001217 break;
1218 }
1219 }
1220 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001221
1222 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001223 in->ec_opened = true;
1224 }
1225 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001226 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1227 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1228 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001229 snd_device = usecase->in_snd_device;
1230 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001231 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001232 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001233
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001234#ifdef DS1_DOLBY_DAP_ENABLED
1235 audio_extn_dolby_set_dmid(adev);
1236 audio_extn_dolby_set_endpoint(adev);
1237#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001238 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001239 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301240 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001241 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001242 if (audio_extn_is_maxx_audio_enabled())
1243 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301244 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301245 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1246 out = usecase->stream.out;
1247 if (out && out->compr)
1248 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1249 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301250
1251 if (usecase->type == PCM_CAPTURE) {
1252 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001253 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301254 ALOGD("%s: set custom mtmx params v1", __func__);
1255 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1256 }
1257 } else {
1258 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1259 }
Manish Dewangan58229382017-02-02 15:48:41 +05301260
Andy Hung756ecc12018-10-19 17:47:12 -07001261 // we shouldn't truncate mixer_path
1262 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1263 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1264 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001265 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001266 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301267 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1268 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1269 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1270 if (parms) {
1271 audio_extn_fm_set_parameters(adev, parms);
1272 str_parms_destroy(parms);
1273 }
1274 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275 ALOGV("%s: exit", __func__);
1276 return 0;
1277}
1278
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001279int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001280 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001282 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001283 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301284 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001285
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301286 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001287 return -EINVAL;
1288
1289 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301290 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001291 snd_device = usecase->in_snd_device;
1292 else
1293 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001294
1295 /* disable island and power mode on supported device for voice call */
1296 if (usecase->type == VOICE_CALL) {
1297 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1298 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1299 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1300 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1301 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1302 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
1303 ALOGD("%s: disable island cfg and power mode in voice tx path",
1304 __func__);
1305 }
1306 }
1307 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1308 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1309 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1310 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1311 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1312 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1313 ALOGD("%s: disable island cfg and power mode in voice rx path",
1314 __func__);
1315 }
1316 }
1317 }
1318
Andy Hung756ecc12018-10-19 17:47:12 -07001319 // we shouldn't truncate mixer_path
1320 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1321 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1322 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001323 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001324 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001325 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001326 if (usecase->type == PCM_CAPTURE) {
1327 struct stream_in *in = usecase->stream.in;
1328 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001329 struct listnode out_devices;
1330 list_init(&out_devices);
1331 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001332 in->ec_opened = false;
1333 }
1334 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001335 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301336 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301337
1338 if (usecase->type == PCM_CAPTURE) {
1339 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001340 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301341 ALOGD("%s: reset custom mtmx params v1", __func__);
1342 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1343 }
1344 } else {
1345 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1346 }
1347
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001348 if ((usecase->type == PCM_PLAYBACK) &&
1349 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301350 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001352 ALOGV("%s: exit", __func__);
1353 return 0;
1354}
1355
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001356int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001357 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001358{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301359 int i, num_devices = 0;
1360 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001361 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1362
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001363 if (snd_device < SND_DEVICE_MIN ||
1364 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001365 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001366 return -EINVAL;
1367 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001368
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001369 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001370 ALOGE("%s: Invalid sound device returned", __func__);
1371 return -EINVAL;
1372 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001373
1374 adev->snd_dev_ref_cnt[snd_device]++;
1375
1376 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1377 (platform_split_snd_device(adev->platform,
1378 snd_device,
1379 &num_devices,
1380 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001381 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001382 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001383 return 0;
1384 }
1385
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001386 if (audio_extn_spkr_prot_is_enabled())
1387 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001388
Aalique Grahame22e49102018-12-18 14:23:57 -08001389 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1390
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001391 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1392 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001393 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1394 goto err;
1395 }
1396 audio_extn_dev_arbi_acquire(snd_device);
1397 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001398 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001399 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001400 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001401 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001402 } else if (platform_split_snd_device(adev->platform,
1403 snd_device,
1404 &num_devices,
1405 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301406 for (i = 0; i < num_devices; i++) {
1407 enable_snd_device(adev, new_snd_devices[i]);
1408 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001409 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001410 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001411 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301412
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001413 /* enable island and power mode on supported device */
1414 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1415 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1416 platform_set_island_cfg_on_device(adev, snd_device, true);
1417 platform_set_power_mode_on_device(adev, snd_device, true);
1418 ALOGD("%s: enable island cfg and power mode on: %s",
1419 __func__, device_name);
1420 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301421
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301422 if (SND_DEVICE_OUT_BT_A2DP == snd_device) {
1423 if (audio_extn_a2dp_start_playback() < 0) {
1424 ALOGE(" fail to configure A2dp Source control path ");
1425 goto err;
1426 } else {
1427 adev->a2dp_started = true;
1428 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001429 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001430
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001431 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1432 (audio_extn_a2dp_start_capture() < 0)) {
1433 ALOGE(" fail to configure A2dp Sink control path ");
1434 goto err;
1435 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301436
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001437 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1438 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1439 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1440 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1441 ALOGE(" fail to configure sco control path ");
1442 goto err;
1443 }
Zhou Song12c29502019-03-16 10:37:18 +08001444 }
1445
Zhou Song331c8e52019-08-26 14:16:12 +08001446 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001447 /* due to the possibility of calibration overwrite between listen
1448 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001449 audio_extn_sound_trigger_update_device_status(snd_device,
1450 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301451 audio_extn_listen_update_device_status(snd_device,
1452 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001453 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001454 audio_extn_sound_trigger_update_device_status(snd_device,
1455 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301456 audio_extn_listen_update_device_status(snd_device,
1457 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001458 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001459 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001460 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001461 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301462
1463 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1464 !adev->native_playback_enabled &&
1465 audio_is_true_native_stream_active(adev)) {
1466 ALOGD("%s: %d: napb: enabling native mode in hardware",
1467 __func__, __LINE__);
1468 audio_route_apply_and_update_path(adev->audio_route,
1469 "true-native-mode");
1470 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301471 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301472 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1473 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001474 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001475 ALOGD("%s: init ec ref loopback", __func__);
1476 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1477 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001479 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001480err:
1481 adev->snd_dev_ref_cnt[snd_device]--;
1482 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001483}
1484
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001485int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001486 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301488 int i, num_devices = 0;
1489 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001490 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1491
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001492 if (snd_device < SND_DEVICE_MIN ||
1493 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001494 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001495 return -EINVAL;
1496 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001497
1498 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1499 ALOGE("%s: Invalid sound device returned", __func__);
1500 return -EINVAL;
1501 }
1502
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001503 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1504 ALOGE("%s: device ref cnt is already 0", __func__);
1505 return -EINVAL;
1506 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001507
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001508 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001509
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001510
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001511 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001512 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301513
Aalique Grahame22e49102018-12-18 14:23:57 -08001514 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1515
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001516 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1517 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001518 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001519
1520 // when speaker device is disabled, reset swap.
1521 // will be renabled on usecase start
1522 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001523 } else if (platform_split_snd_device(adev->platform,
1524 snd_device,
1525 &num_devices,
1526 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301527 for (i = 0; i < num_devices; i++) {
1528 disable_snd_device(adev, new_snd_devices[i]);
1529 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001530 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001531 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001532 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001533 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001534
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301535 if (snd_device == SND_DEVICE_OUT_BT_A2DP) {
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301536 audio_extn_a2dp_stop_playback();
Revathi Uddarajub26e3932020-06-10 14:51:02 +05301537 adev->a2dp_started = false;
1538 } else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001539 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001540 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001541 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301542 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001543 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301544 adev->native_playback_enabled) {
1545 ALOGD("%s: %d: napb: disabling native mode in hardware",
1546 __func__, __LINE__);
1547 audio_route_reset_and_update_path(adev->audio_route,
1548 "true-native-mode");
1549 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001550 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301551 adev->asrc_mode_enabled) {
1552 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301553 disable_asrc_mode(adev);
1554 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001555 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301556 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001557 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001558 ALOGD("%s: deinit ec ref loopback", __func__);
1559 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1560 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001561
1562 audio_extn_utils_release_snd_device(snd_device);
1563 } else {
1564 if (platform_split_snd_device(adev->platform,
1565 snd_device,
1566 &num_devices,
1567 new_snd_devices) == 0) {
1568 for (i = 0; i < num_devices; i++) {
1569 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1570 }
1571 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001572 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001574 return 0;
1575}
1576
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001577/*
1578 legend:
1579 uc - existing usecase
1580 new_uc - new usecase
1581 d1, d11, d2 - SND_DEVICE enums
1582 a1, a2 - corresponding ANDROID device enums
1583 B1, B2 - backend strings
1584
1585case 1
1586 uc->dev d1 (a1) B1
1587 new_uc->dev d1 (a1), d2 (a2) B1, B2
1588
1589 resolution: disable and enable uc->dev on d1
1590
1591case 2
1592 uc->dev d1 (a1) B1
1593 new_uc->dev d11 (a1) B1
1594
1595 resolution: need to switch uc since d1 and d11 are related
1596 (e.g. speaker and voice-speaker)
1597 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1598
1599case 3
1600 uc->dev d1 (a1) B1
1601 new_uc->dev d2 (a2) B2
1602
1603 resolution: no need to switch uc
1604
1605case 4
1606 uc->dev d1 (a1) B1
1607 new_uc->dev d2 (a2) B1
1608
1609 resolution: disable enable uc-dev on d2 since backends match
1610 we cannot enable two streams on two different devices if they
1611 share the same backend. e.g. if offload is on speaker device using
1612 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1613 using the same backend, offload must also be switched to voice-handset.
1614
1615case 5
1616 uc->dev d1 (a1) B1
1617 new_uc->dev d1 (a1), d2 (a2) B1
1618
1619 resolution: disable enable uc-dev on d2 since backends match
1620 we cannot enable two streams on two different devices if they
1621 share the same backend.
1622
1623case 6
1624 uc->dev d1 (a1) B1
1625 new_uc->dev d2 (a1) B2
1626
1627 resolution: no need to switch
1628
1629case 7
1630 uc->dev d1 (a1), d2 (a2) B1, B2
1631 new_uc->dev d1 (a1) B1
1632
1633 resolution: no need to switch
1634
Zhou Song4ba65882018-07-09 14:48:07 +08001635case 8
1636 uc->dev d1 (a1) B1
1637 new_uc->dev d11 (a1), d2 (a2) B1, B2
1638 resolution: compared to case 1, for this case, d1 and d11 are related
1639 then need to do the same as case 2 to siwtch to new uc
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 {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001686 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301687 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001688 // check if d1 is related to any of d3's
1689 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001690 return d1; // case 1
1691 else
1692 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001693 }
1694 } else {
1695 if (platform_check_backends_match(d1, d2)) {
1696 return d2; // case 2, 4
1697 } else {
1698 return d1; // case 6, 3
1699 }
1700 }
1701
1702end:
1703 return d2; // return whatever was calculated before.
1704}
1705
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001706static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301707 struct audio_usecase *uc_info,
1708 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001709{
1710 struct listnode *node;
1711 struct audio_usecase *usecase;
1712 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301713 snd_device_t uc_derive_snd_device;
1714 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001715 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1716 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001717 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301718 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001719 /*
1720 * This function is to make sure that all the usecases that are active on
1721 * the hardware codec backend are always routed to any one device that is
1722 * handled by the hardware codec.
1723 * For example, if low-latency and deep-buffer usecases are currently active
1724 * on speaker and out_set_parameters(headset) is received on low-latency
1725 * output, then we have to make sure deep-buffer is also switched to headset,
1726 * because of the limitation that both the devices cannot be enabled
1727 * at the same time as they share the same backend.
1728 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001729 /*
1730 * This call is to check if we need to force routing for a particular stream
1731 * If there is a backend configuration change for the device when a
1732 * new stream starts, then ADM needs to be closed and re-opened with the new
1733 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001734 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001735 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001736 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1737 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301738 /* For a2dp device reconfigure all active sessions
1739 * with new AFE encoder format based on a2dp state
1740 */
1741 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1742 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1743 audio_extn_a2dp_is_force_device_switch()) {
1744 force_routing = true;
1745 force_restart_session = true;
1746 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001747
1748 /*
1749 * Island cfg and power mode config needs to set before AFE port start.
1750 * Set force routing in case of voice device was enable before.
1751 */
1752 if (uc_info->type == VOICE_CALL &&
1753 voice_extn_is_voice_power_mode_supported() &&
1754 platform_check_and_update_island_power_status(adev->platform,
1755 uc_info,
1756 snd_device)) {
1757 force_routing = true;
1758 ALOGD("%s:becf: force routing %d for power mode supported device",
1759 __func__, force_routing);
1760 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301761 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1762
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001763 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001764 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001765 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001766 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1767 switch_device[i] = false;
1768
1769 list_for_each(node, &adev->usecase_list) {
1770 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001771
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301772 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1773 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301774 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301775 platform_get_snd_device_name(usecase->out_snd_device),
1776 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301777 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1778 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301779 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1780 usecase, uc_info, snd_device);
1781 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001782 (is_codec_backend_out_device_type(&usecase->device_list) ||
1783 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1784 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1785 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1786 is_a2dp_out_device_type(&usecase->device_list) ||
1787 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301788 ((force_restart_session) ||
1789 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301790 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1791 __func__, use_case_table[usecase->id],
1792 platform_get_snd_device_name(usecase->out_snd_device));
1793 disable_audio_route(adev, usecase);
1794 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301795 /* Enable existing usecase on derived playback device */
1796 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301797 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301798 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001799 }
1800 }
1801
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301802 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1803 num_uc_to_switch);
1804
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001805 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001806 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001807
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301808 /* Make sure the previous devices to be disabled first and then enable the
1809 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001810 list_for_each(node, &adev->usecase_list) {
1811 usecase = node_to_item(node, struct audio_usecase, list);
1812 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001813 /* Check if output sound device to be switched can be split and if any
1814 of the split devices match with derived sound device */
1815 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1816 &num_devices, split_snd_devices) == 0) {
1817 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1818 for (i = 0; i < num_devices; i++) {
1819 /* Disable devices that do not match with derived sound device */
1820 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1821 disable_snd_device(adev, split_snd_devices[i]);
1822 }
1823 } else {
1824 disable_snd_device(adev, usecase->out_snd_device);
1825 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001826 }
1827 }
1828
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001829 list_for_each(node, &adev->usecase_list) {
1830 usecase = node_to_item(node, struct audio_usecase, list);
1831 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001832 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1833 &num_devices, split_snd_devices) == 0) {
1834 /* Enable derived sound device only if it does not match with
1835 one of the split sound devices. This is because the matching
1836 sound device was not disabled */
1837 bool should_enable = true;
1838 for (i = 0; i < num_devices; i++) {
1839 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1840 should_enable = false;
1841 break;
1842 }
1843 }
1844 if (should_enable)
1845 enable_snd_device(adev, derive_snd_device[usecase->id]);
1846 } else {
1847 enable_snd_device(adev, derive_snd_device[usecase->id]);
1848 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001849 }
1850 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001851
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001852 /* Re-route all the usecases on the shared backend other than the
1853 specified usecase to new snd devices */
1854 list_for_each(node, &adev->usecase_list) {
1855 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301856 /* Update the out_snd_device only before enabling the audio route */
1857 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301858 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301859 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301860 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301861 use_case_table[usecase->id],
1862 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001863 /* Update voc calibration before enabling VoIP route */
1864 if (usecase->type == VOIP_CALL)
1865 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001866 usecase->out_snd_device,
1867 platform_get_input_snd_device(
1868 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301869 &uc_info->device_list,
1870 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301871 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301872 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001873 out_set_voip_volume(&usecase->stream.out->stream,
1874 usecase->stream.out->volume_l,
1875 usecase->stream.out->volume_r);
1876 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301877 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001878 }
1879 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001880 }
1881}
1882
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301883static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001884 struct audio_usecase *uc_info,
1885 snd_device_t snd_device)
1886{
1887 struct listnode *node;
1888 struct audio_usecase *usecase;
1889 bool switch_device[AUDIO_USECASE_MAX];
1890 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001891 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001892 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001893
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301894 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1895 snd_device);
1896 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301897
1898 /*
1899 * Make sure out devices is checked against out codec backend device and
1900 * also in devices against in codec backend. Checking out device against in
1901 * codec backend or vice versa causes issues.
1902 */
1903 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001904 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001905
1906 /*
1907 * Island cfg and power mode config needs to set before AFE port start.
1908 * Set force routing in case of voice device was enable before.
1909 */
1910
1911 if (uc_info->type == VOICE_CALL &&
1912 voice_extn_is_voice_power_mode_supported() &&
1913 platform_check_and_update_island_power_status(adev->platform,
1914 uc_info,
1915 snd_device)) {
1916 force_routing = true;
1917 ALOGD("%s:becf: force routing %d for power mode supported device",
1918 __func__, force_routing);
1919 }
1920
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001921 /*
1922 * This function is to make sure that all the active capture usecases
1923 * are always routed to the same input sound device.
1924 * For example, if audio-record and voice-call usecases are currently
1925 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1926 * is received for voice call then we have to make sure that audio-record
1927 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1928 * because of the limitation that two devices cannot be enabled
1929 * at the same time if they share the same backend.
1930 */
1931 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1932 switch_device[i] = false;
1933
1934 list_for_each(node, &adev->usecase_list) {
1935 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301936 /*
1937 * TODO: Enhance below condition to handle BT sco/USB multi recording
1938 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301939
1940 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1941 (usecase->in_snd_device != snd_device || force_routing));
1942 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1943 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1944 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001945 ((backend_check_cond &&
1946 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001947 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001948 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001949 is_single_device_type_equal(&usecase->device_list,
1950 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001951 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001952 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001953 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301954 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001955 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001956 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001957 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001958 switch_device[usecase->id] = true;
1959 num_uc_to_switch++;
1960 }
1961 }
1962
1963 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001964 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001965
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301966 /* Make sure the previous devices to be disabled first and then enable the
1967 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001968 list_for_each(node, &adev->usecase_list) {
1969 usecase = node_to_item(node, struct audio_usecase, list);
1970 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001971 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001972 }
1973 }
1974
1975 list_for_each(node, &adev->usecase_list) {
1976 usecase = node_to_item(node, struct audio_usecase, list);
1977 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001978 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001979 }
1980 }
1981
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001982 /* Re-route all the usecases on the shared backend other than the
1983 specified usecase to new snd devices */
1984 list_for_each(node, &adev->usecase_list) {
1985 usecase = node_to_item(node, struct audio_usecase, list);
1986 /* Update the in_snd_device only before enabling the audio route */
1987 if (switch_device[usecase->id] ) {
1988 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001989 if (usecase->type != VOICE_CALL) {
1990 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301991 if (usecase->type == VOIP_CALL) {
1992 snd_device_t voip_snd_device;
1993 voip_snd_device = platform_get_output_snd_device(adev->platform,
1994 uc_info->stream.out,
1995 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08001996 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301997 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08001998 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05301999 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302000 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002001 }
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
Avinash Vaish71a8b972014-07-24 15:36:33 +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);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302953 enable_audio_route_for_voice_usecases(adev, usecase);
2954 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002955
sangwoo170731f2013-06-08 15:36:36 +09002956 usecase->in_snd_device = in_snd_device;
2957 usecase->out_snd_device = out_snd_device;
2958
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302959 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2960 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302961 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002962 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002963 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002964 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2965 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2966 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2967 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2968 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2969 /*
2970 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2971 * configured device sample rate, if not update the COPP rate to be equal to the
2972 * device sample rate, else open COPP at stream sample rate
2973 */
2974 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2975 usecase->stream.out->sample_rate,
2976 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302977 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302978 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2979 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302980 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002981 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2982 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2983 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2984 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002985 }
2986 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002987
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002988 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002989
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002990 /* If input stream is already running then effect needs to be
2991 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002992 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002993 check_and_enable_effect(adev);
2994
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002995 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002996 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302997 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002998 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2999
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003000 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303001 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003002 voice_extn_compress_voip_is_started(adev))
3003 voice_set_sidetone(adev, out_snd_device, true);
3004 }
3005
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003006 /* Applicable only on the targets that has external modem.
3007 * Enable device command should be sent to modem only after
3008 * enabling voice call mixer controls
3009 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003010 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003011 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3012 out_snd_device,
3013 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303014
3015 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003016 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303017 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003018 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303019 if (is_bt_soc_on(adev) == false){
3020 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003021 if (in->pcm != NULL)
3022 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303023 }
3024 }
3025 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3026 && usecase->stream.out->started) {
3027 if (is_bt_soc_on(adev) == false) {
3028 ALOGD("BT SCO/A2DP disconnected while in connection");
3029 out_standby_l(&usecase->stream.out->stream.common);
3030 }
3031 }
3032 } else if ((usecase->stream.out != NULL) &&
3033 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303034 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3035 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003036 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303037 usecase->stream.out->started) {
3038 if (is_bt_soc_on(adev) == false) {
3039 ALOGD("BT SCO/A2dp disconnected while in connection");
3040 out_standby_l(&usecase->stream.out->stream.common);
3041 }
3042 }
3043 }
3044
Yung Ti Su70cb8242018-06-22 17:38:47 +08003045 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003046 struct stream_out *voip_out = voip_usecase->stream.out;
3047 audio_extn_utils_send_app_type_gain(adev,
3048 voip_out->app_type_cfg.app_type,
3049 &voip_out->app_type_cfg.gain[0]);
3050 }
3051
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303052 ALOGD("%s: done",__func__);
3053
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054 return status;
3055}
3056
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057static int stop_input_stream(struct stream_in *in)
3058{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303059 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303061
3062 if (in == NULL) {
3063 ALOGE("%s: stream_in ptr is NULL", __func__);
3064 return -EINVAL;
3065 }
3066
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003068 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069
Eric Laurent994a6932013-07-17 11:51:42 -07003070 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003071 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072 uc_info = get_usecase_from_list(adev, in->usecase);
3073 if (uc_info == NULL) {
3074 ALOGE("%s: Could not find the usecase (%d) in the list",
3075 __func__, in->usecase);
3076 return -EINVAL;
3077 }
3078
Carter Hsu2e429db2019-05-14 18:50:52 +08003079 priority_in = get_priority_input(adev);
3080
Derek Chenea197282019-01-07 17:35:01 -08003081 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3082 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003083
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003084 /* Close in-call recording streams */
3085 voice_check_and_stop_incall_rec_usecase(adev, in);
3086
Eric Laurent150dbfe2013-02-27 14:31:02 -08003087 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003088 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003089
3090 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003091 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003093 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303094 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3095
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003096 list_remove(&uc_info->list);
3097 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098
Carter Hsu2e429db2019-05-14 18:50:52 +08003099 if (priority_in == in) {
3100 priority_in = get_priority_input(adev);
3101 if (priority_in)
3102 select_devices(adev, priority_in->usecase);
3103 }
3104
Vatsal Buchac09ae062018-11-14 13:25:08 +05303105 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003106 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107 return ret;
3108}
3109
3110int start_input_stream(struct stream_in *in)
3111{
3112 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003113 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303115
3116 if (in == NULL) {
3117 ALOGE("%s: stream_in ptr is NULL", __func__);
3118 return -EINVAL;
3119 }
3120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003122 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003123 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124
Mingming Yin2664a5b2015-09-03 10:53:11 -07003125 if (get_usecase_from_list(adev, usecase) == NULL)
3126 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303127 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3128 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003129
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303130 if (CARD_STATUS_OFFLINE == in->card_status||
3131 CARD_STATUS_OFFLINE == adev->card_status) {
3132 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303133 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303134 goto error_config;
3135 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303136
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003137 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303138 if (!adev->bt_sco_on) {
3139 ALOGE("%s: SCO profile is not ready, return error", __func__);
3140 ret = -EIO;
3141 goto error_config;
3142 }
3143 }
3144
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003145 /* Check if source matches incall recording usecase criteria */
3146 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3147 if (ret)
3148 goto error_config;
3149 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003150 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3151
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303152 if (audio_extn_cin_attached_usecase(in))
3153 audio_extn_cin_acquire_usecase(in);
3154
Mingming Yin2664a5b2015-09-03 10:53:11 -07003155 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3156 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3157 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003158 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003159 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003160
Eric Laurentb23d5282013-05-14 15:27:20 -07003161 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162 if (in->pcm_device_id < 0) {
3163 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3164 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003165 ret = -EINVAL;
3166 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003170
3171 if (!uc_info) {
3172 ret = -ENOMEM;
3173 goto error_config;
3174 }
3175
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176 uc_info->id = in->usecase;
3177 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003178 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003179 list_init(&uc_info->device_list);
3180 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003181 uc_info->in_snd_device = SND_DEVICE_NONE;
3182 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003184 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003185 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303186 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3187 adev->perf_lock_opts,
3188 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003189 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190
Derek Chenea197282019-01-07 17:35:01 -08003191 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3192 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003193
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303194 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3195
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303196 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303197 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303198 if (ret)
3199 goto error_open;
3200 else
3201 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003202 }
3203
Haynes Mathew George16081042017-05-31 17:16:49 -07003204 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003205 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003206 ALOGE("%s: pcm stream not ready", __func__);
3207 goto error_open;
3208 }
3209 ret = pcm_start(in->pcm);
3210 if (ret < 0) {
3211 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3212 goto error_open;
3213 }
3214 } else {
3215 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3216 unsigned int pcm_open_retry_count = 0;
3217
Zhou Song62ea0282020-03-22 19:53:01 +08003218 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3219 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003220 flags |= PCM_MMAP | PCM_NOIRQ;
3221 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3222 } else if (in->realtime) {
3223 flags |= PCM_MMAP | PCM_NOIRQ;
3224 }
3225
Garmond Leunge2433c32017-09-28 21:51:22 -07003226 if (audio_extn_ffv_get_stream() == in) {
3227 ALOGD("%s: ffv stream, update pcm config", __func__);
3228 audio_extn_ffv_update_pcm_config(&config);
3229 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003230 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3231 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3232
3233 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003234 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003235 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003236 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003237 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303238 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303239 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3240 adev->card_status = CARD_STATUS_OFFLINE;
3241 in->card_status = CARD_STATUS_OFFLINE;
3242 ret = -EIO;
3243 goto error_open;
3244 }
3245
Haynes Mathew George16081042017-05-31 17:16:49 -07003246 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3247 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3248 if (in->pcm != NULL) {
3249 pcm_close(in->pcm);
3250 in->pcm = NULL;
3251 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003252 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003253 ret = -EIO;
3254 goto error_open;
3255 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003256 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003257 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3258 continue;
3259 }
3260 break;
3261 }
3262
3263 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003264 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003265 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003266 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003267 if (ret < 0) {
3268 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3269 pcm_close(in->pcm);
3270 in->pcm = NULL;
3271 goto error_open;
3272 }
3273 register_in_stream(in);
3274 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003275 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003276 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003277 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003278 if (ret < 0) {
3279 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003280 pcm_close(in->pcm);
3281 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003282 goto error_open;
3283 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003284 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003285 }
3286
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003287 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003288 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3289 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003290
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003291 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303292 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3293
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303294done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003295 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303296 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003297 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303298 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003299 return ret;
3300
3301error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003302 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303303 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003305
Eric Laurentc8400632013-02-14 19:04:54 -08003306error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303307 /*
3308 * sleep 50ms to allow sufficient time for kernel
3309 * drivers to recover incases like SSR.
3310 */
3311 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003312 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303313 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003314 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315}
3316
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003317void lock_input_stream(struct stream_in *in)
3318{
3319 pthread_mutex_lock(&in->pre_lock);
3320 pthread_mutex_lock(&in->lock);
3321 pthread_mutex_unlock(&in->pre_lock);
3322}
3323
3324void lock_output_stream(struct stream_out *out)
3325{
3326 pthread_mutex_lock(&out->pre_lock);
3327 pthread_mutex_lock(&out->lock);
3328 pthread_mutex_unlock(&out->pre_lock);
3329}
3330
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003331/* must be called with out->lock locked */
3332static int send_offload_cmd_l(struct stream_out* out, int command)
3333{
3334 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3335
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003336 if (!cmd) {
3337 ALOGE("failed to allocate mem for command 0x%x", command);
3338 return -ENOMEM;
3339 }
3340
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003341 ALOGVV("%s %d", __func__, command);
3342
3343 cmd->cmd = command;
3344 list_add_tail(&out->offload_cmd_list, &cmd->node);
3345 pthread_cond_signal(&out->offload_cond);
3346 return 0;
3347}
3348
3349/* must be called iwth out->lock locked */
3350static void stop_compressed_output_l(struct stream_out *out)
3351{
3352 out->offload_state = OFFLOAD_STATE_IDLE;
3353 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003354 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003355 if (out->compr != NULL) {
3356 compress_stop(out->compr);
3357 while (out->offload_thread_blocked) {
3358 pthread_cond_wait(&out->cond, &out->lock);
3359 }
3360 }
3361}
3362
Varun Balaraje49253e2017-07-06 19:48:56 +05303363bool is_interactive_usecase(audio_usecase_t uc_id)
3364{
3365 unsigned int i;
3366 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3367 if (uc_id == interactive_usecases[i])
3368 return true;
3369 }
3370 return false;
3371}
3372
3373static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3374{
3375 audio_usecase_t ret_uc = USECASE_INVALID;
3376 unsigned int intract_uc_index;
3377 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3378
3379 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3380 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3381 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3382 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3383 ret_uc = interactive_usecases[intract_uc_index];
3384 break;
3385 }
3386 }
3387
3388 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3389 return ret_uc;
3390}
3391
3392static void free_interactive_usecase(struct audio_device *adev,
3393 audio_usecase_t uc_id)
3394{
3395 unsigned int interact_uc_index;
3396 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3397
3398 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3399 if (interactive_usecases[interact_uc_index] == uc_id) {
3400 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3401 break;
3402 }
3403 }
3404 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3405}
3406
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003407bool is_offload_usecase(audio_usecase_t uc_id)
3408{
3409 unsigned int i;
3410 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3411 if (uc_id == offload_usecases[i])
3412 return true;
3413 }
3414 return false;
3415}
3416
Dhananjay Kumarac341582017-02-23 23:42:25 +05303417static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003418{
vivek mehta446c3962015-09-14 10:57:35 -07003419 audio_usecase_t ret_uc = USECASE_INVALID;
3420 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003421 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003422 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303423 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003424 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3425 else
3426 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003427
vivek mehta446c3962015-09-14 10:57:35 -07003428 pthread_mutex_lock(&adev->lock);
3429 if (get_usecase_from_list(adev, ret_uc) != NULL)
3430 ret_uc = USECASE_INVALID;
3431 pthread_mutex_unlock(&adev->lock);
3432
3433 return ret_uc;
3434 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003435
3436 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003437 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3438 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3439 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3440 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003441 break;
3442 }
3443 }
vivek mehta446c3962015-09-14 10:57:35 -07003444
3445 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3446 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003447}
3448
3449static void free_offload_usecase(struct audio_device *adev,
3450 audio_usecase_t uc_id)
3451{
vivek mehta446c3962015-09-14 10:57:35 -07003452 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003453 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003454
3455 if (!adev->multi_offload_enable)
3456 return;
3457
3458 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3459 if (offload_usecases[offload_uc_index] == uc_id) {
3460 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003461 break;
3462 }
3463 }
3464 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3465}
3466
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003467static void *offload_thread_loop(void *context)
3468{
3469 struct stream_out *out = (struct stream_out *) context;
3470 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003471 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003472
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003473 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003474 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003475 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3476
3477 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003478 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003479 out->offload_state = OFFLOAD_STATE_IDLE;
3480 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003481 for (;;) {
3482 struct offload_cmd *cmd = NULL;
3483 stream_callback_event_t event;
3484 bool send_callback = false;
3485
3486 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3487 __func__, list_empty(&out->offload_cmd_list),
3488 out->offload_state);
3489 if (list_empty(&out->offload_cmd_list)) {
3490 ALOGV("%s SLEEPING", __func__);
3491 pthread_cond_wait(&out->offload_cond, &out->lock);
3492 ALOGV("%s RUNNING", __func__);
3493 continue;
3494 }
3495
3496 item = list_head(&out->offload_cmd_list);
3497 cmd = node_to_item(item, struct offload_cmd, node);
3498 list_remove(item);
3499
3500 ALOGVV("%s STATE %d CMD %d out->compr %p",
3501 __func__, out->offload_state, cmd->cmd, out->compr);
3502
3503 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3504 free(cmd);
3505 break;
3506 }
3507
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003508 // allow OFFLOAD_CMD_ERROR reporting during standby
3509 // this is needed to handle failures during compress_open
3510 // Note however that on a pause timeout, the stream is closed
3511 // and no offload usecase will be active. Therefore this
3512 // special case is needed for compress_open failures alone
3513 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3514 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003515 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003516 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003517 pthread_cond_signal(&out->cond);
3518 continue;
3519 }
3520 out->offload_thread_blocked = true;
3521 pthread_mutex_unlock(&out->lock);
3522 send_callback = false;
3523 switch(cmd->cmd) {
3524 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003525 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003526 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003527 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003528 send_callback = true;
3529 event = STREAM_CBK_EVENT_WRITE_READY;
3530 break;
3531 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003532 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303533 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003534 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303535 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003536 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303537 if (ret < 0)
3538 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303539 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303540 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003541 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003542 else
3543 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003544 if (-ENETRESET != ret && !(-EINTR == ret &&
3545 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303546 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303547 pthread_mutex_lock(&out->lock);
3548 out->send_new_metadata = 1;
3549 out->send_next_track_params = true;
3550 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303551 event = STREAM_CBK_EVENT_DRAIN_READY;
3552 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3553 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303554 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003555 break;
3556 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003557 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003558 ret = compress_drain(out->compr);
3559 ALOGD("copl(%p):out of compress_drain", out);
3560 // EINTR check avoids drain interruption due to SSR
3561 if (-ENETRESET != ret && !(-EINTR == ret &&
3562 CARD_STATUS_OFFLINE == out->card_status)) {
3563 send_callback = true;
3564 event = STREAM_CBK_EVENT_DRAIN_READY;
3565 } else
3566 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003567 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303568 case OFFLOAD_CMD_ERROR:
3569 ALOGD("copl(%p): sending error callback to AF", out);
3570 send_callback = true;
3571 event = STREAM_CBK_EVENT_ERROR;
3572 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003573 default:
3574 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3575 break;
3576 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003577 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003578 out->offload_thread_blocked = false;
3579 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003580 if (send_callback && out->client_callback) {
3581 ALOGVV("%s: sending client_callback event %d", __func__, event);
3582 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003583 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003584 free(cmd);
3585 }
3586
3587 pthread_cond_signal(&out->cond);
3588 while (!list_empty(&out->offload_cmd_list)) {
3589 item = list_head(&out->offload_cmd_list);
3590 list_remove(item);
3591 free(node_to_item(item, struct offload_cmd, node));
3592 }
3593 pthread_mutex_unlock(&out->lock);
3594
3595 return NULL;
3596}
3597
3598static int create_offload_callback_thread(struct stream_out *out)
3599{
3600 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3601 list_init(&out->offload_cmd_list);
3602 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3603 offload_thread_loop, out);
3604 return 0;
3605}
3606
3607static int destroy_offload_callback_thread(struct stream_out *out)
3608{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003609 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003610 stop_compressed_output_l(out);
3611 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3612
3613 pthread_mutex_unlock(&out->lock);
3614 pthread_join(out->offload_thread, (void **) NULL);
3615 pthread_cond_destroy(&out->offload_cond);
3616
3617 return 0;
3618}
3619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620static int stop_output_stream(struct stream_out *out)
3621{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303622 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 struct audio_usecase *uc_info;
3624 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003625 bool has_voip_usecase =
3626 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627
Eric Laurent994a6932013-07-17 11:51:42 -07003628 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003629 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 uc_info = get_usecase_from_list(adev, out->usecase);
3631 if (uc_info == NULL) {
3632 ALOGE("%s: Could not find the usecase (%d) in the list",
3633 __func__, out->usecase);
3634 return -EINVAL;
3635 }
3636
Derek Chenea197282019-01-07 17:35:01 -08003637 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3638 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003639
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003640 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303641 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003642 if (adev->visualizer_stop_output != NULL)
3643 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003644
3645 audio_extn_dts_remove_state_notifier_node(out->usecase);
3646
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003647 if (adev->offload_effects_stop_output != NULL)
3648 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003649 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3650 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3651 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003652 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003653
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003654 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3655 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003656 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003657 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003658
Eric Laurent150dbfe2013-02-27 14:31:02 -08003659 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003660 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003661
3662 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003663 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664
Aalique Grahame22e49102018-12-18 14:23:57 -08003665 audio_extn_extspk_update(adev->extspk);
3666
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003667 if (is_offload_usecase(out->usecase)) {
3668 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3669 adev->dsp_bit_width_enforce_mode,
3670 false);
3671 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003672 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003673 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3674 false);
3675
3676 if (ret != 0)
3677 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3678 /* default service interval was successfully updated,
3679 reopen USB backend with new service interval */
3680 ret = 0;
3681 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003682
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003683 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303684 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003685 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303686 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003687 ALOGV("Disable passthrough , reset mixer to pcm");
3688 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003689#ifdef AUDIO_GKI_ENABLED
3690 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3691 out->compr_config.codec->reserved[0] = 0;
3692#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003693 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003694#endif
Mingming Yin21854652016-04-13 11:54:02 -07003695 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003696 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3697 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003698
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303699 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003700 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303701 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303702
Manish Dewangan21a850a2017-08-14 12:03:55 +05303703 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003704 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3705 if (ret < 0)
3706 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3707 }
3708
juyuchen2d415992018-11-16 14:15:16 +08003709 /* 1) media + voip output routing to handset must route media back to
3710 speaker when voip stops.
3711 2) trigger voip input to reroute when voip output changes to
3712 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003713 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003714 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003715 struct listnode *node;
3716 struct audio_usecase *usecase;
3717 list_for_each(node, &adev->usecase_list) {
3718 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003719 if ((usecase->type == PCM_CAPTURE &&
3720 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3721 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003722 continue;
3723
3724 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3725 __func__, usecase->id, use_case_table[usecase->id],
3726 out->usecase, use_case_table[out->usecase]);
3727 select_devices(adev, usecase->id);
3728 }
3729 }
3730
Garmond Leung5fd0b552018-04-17 11:56:12 -07003731 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003732 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733 return ret;
3734}
3735
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003736struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3737 unsigned int flags, unsigned int pcm_open_retry_count,
3738 struct pcm_config *config)
3739{
3740 struct pcm* pcm = NULL;
3741
3742 while (1) {
3743 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3744 if (pcm == NULL || !pcm_is_ready(pcm)) {
3745 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3746 if (pcm != NULL) {
3747 pcm_close(pcm);
3748 pcm = NULL;
3749 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003750 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003751 return NULL;
3752
Weiyin Jiang72197252019-10-09 11:49:32 +08003753 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003754 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3755 continue;
3756 }
3757 break;
3758 }
3759
3760 if (pcm_is_ready(pcm)) {
3761 int ret = pcm_prepare(pcm);
3762 if (ret < 0) {
3763 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3764 pcm_close(pcm);
3765 pcm = NULL;
3766 }
3767 }
3768
3769 return pcm;
3770}
3771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772int start_output_stream(struct stream_out *out)
3773{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775 struct audio_usecase *uc_info;
3776 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003777 char mixer_ctl_name[128];
3778 struct mixer_ctl *ctl = NULL;
3779 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303780 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003781 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782
Haynes Mathew George380745d2017-10-04 15:27:45 -07003783 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003784 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3785 ret = -EINVAL;
3786 goto error_config;
3787 }
3788
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003789 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303790 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003791 get_device_types(&out->device_list), is_haptic_usecase);
3792
3793 bool is_speaker_active = compare_device_type(&out->device_list,
3794 AUDIO_DEVICE_OUT_SPEAKER);
3795 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3796 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303797
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303798 if (CARD_STATUS_OFFLINE == out->card_status ||
3799 CARD_STATUS_OFFLINE == adev->card_status) {
3800 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303801 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003802 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303803 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303804
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003805 //Update incall music usecase to reflect correct voice session
3806 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3807 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3808 if (ret != 0) {
3809 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3810 __func__, ret);
3811 goto error_config;
3812 }
3813 }
3814
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003815 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003816 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003817 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303818 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303819 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303820 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3821 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3822 ret = -EAGAIN;
3823 goto error_config;
3824 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303825 }
3826 }
3827 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003828 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303829 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003830 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303831 //combo usecase just by pass a2dp
3832 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003833 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303834 } else {
3835 ALOGE("%s: SCO profile is not ready, return error", __func__);
3836 ret = -EAGAIN;
3837 goto error_config;
3838 }
3839 }
3840 }
3841
Eric Laurentb23d5282013-05-14 15:27:20 -07003842 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003843 if (out->pcm_device_id < 0) {
3844 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3845 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003846 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003847 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 }
3849
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003850 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003851 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3852 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003853 if (adev->haptic_pcm_device_id < 0) {
3854 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3855 __func__, adev->haptic_pcm_device_id, out->usecase);
3856 ret = -EINVAL;
3857 goto error_config;
3858 }
3859 }
3860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003862
3863 if (!uc_info) {
3864 ret = -ENOMEM;
3865 goto error_config;
3866 }
3867
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003868 uc_info->id = out->usecase;
3869 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003870 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003871 list_init(&uc_info->device_list);
3872 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003873 uc_info->in_snd_device = SND_DEVICE_NONE;
3874 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003875
3876 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003877 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003878 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3879 /* USB backend is not reopened immediately.
3880 This is eventually done as part of select_devices */
3881 }
3882
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003883 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884
Wei Wangf7ca6c92017-11-21 14:51:20 -08003885 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303886 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3887 adev->perf_lock_opts,
3888 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303889
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003890 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303891 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303892 if (audio_extn_passthru_is_enabled() &&
3893 audio_extn_passthru_is_passthrough_stream(out)) {
3894 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303895 }
3896 }
3897
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003898 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003899 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303900 if (!a2dp_combo) {
3901 check_a2dp_restore_l(adev, out, false);
3902 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003903 struct listnode dev;
3904 list_init(&dev);
3905 assign_devices(&dev, &out->device_list);
3906 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3907 reassign_device_list(&out->device_list,
3908 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003909 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003910 reassign_device_list(&out->device_list,
3911 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303912 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003913 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303914 }
3915 } else {
Revathi Uddarajub26e3932020-06-10 14:51:02 +05303916 select_devices(adev, out->usecase);
3917 if (is_a2dp_out_device_type(&out->device_list) &&
3918 !adev->a2dp_started) {
3919 if (is_speaker_active || is_speaker_safe_active) {
3920 struct listnode dev;
3921 list_init(&dev);
3922 assign_devices(&dev, &out->device_list);
3923 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3924 reassign_device_list(&out->device_list,
3925 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
3926 else
3927 reassign_device_list(&out->device_list,
3928 AUDIO_DEVICE_OUT_SPEAKER, "");
3929 select_devices(adev, out->usecase);
3930 assign_devices(&out->device_list, &dev);
3931 } else {
3932 ret = -EINVAL;
3933 goto error_open;
3934 }
3935 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303936 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003937
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003938 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3939 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003940 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003941 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003942
Derek Chenea197282019-01-07 17:35:01 -08003943 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3944 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003945
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003946 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3947 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003948
3949 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003950 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003951 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3952 ALOGE("%s: pcm stream not ready", __func__);
3953 goto error_open;
3954 }
3955 ret = pcm_start(out->pcm);
3956 if (ret < 0) {
3957 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3958 goto error_open;
3959 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003960 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003961 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003962 unsigned int flags = PCM_OUT;
3963 unsigned int pcm_open_retry_count = 0;
3964 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3965 flags |= PCM_MMAP | PCM_NOIRQ;
3966 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003967 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003968 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003969 } else
3970 flags |= PCM_MONOTONIC;
3971
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003972 if ((adev->vr_audio_mode_enabled) &&
3973 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3974 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3975 "PCM_Dev %d Topology", out->pcm_device_id);
3976 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3977 if (!ctl) {
3978 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3979 __func__, mixer_ctl_name);
3980 } else {
3981 //if success use ULLPP
3982 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3983 __func__, mixer_ctl_name, out->pcm_device_id);
3984 //There is a still a possibility that some sessions
3985 // that request for FAST|RAW when 3D audio is active
3986 //can go through ULLPP. Ideally we expects apps to
3987 //listen to audio focus and stop concurrent playback
3988 //Also, we will look for mode flag (voice_in_communication)
3989 //before enabling the realtime flag.
3990 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3991 }
3992 }
3993
Surendar Karka91fa3682018-07-02 18:12:12 +05303994 if (out->realtime)
3995 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3996 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3997
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003998 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3999 flags, pcm_open_retry_count,
4000 &(out->config));
4001 if (out->pcm == NULL) {
4002 ret = -EIO;
4003 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004004 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004005
4006 if (is_haptic_usecase) {
4007 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
4008 adev->haptic_pcm_device_id,
4009 flags, pcm_open_retry_count,
4010 &(adev->haptics_config));
4011 // failure to open haptics pcm shouldnt stop audio,
4012 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004013
4014 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4015 ALOGD("%s: enable haptic audio synchronization", __func__);
4016 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4017 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004018 }
4019
Surendar Karka91fa3682018-07-02 18:12:12 +05304020 if (!out->realtime)
4021 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304022 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004023
Zhou Song2b8f28f2017-09-11 10:51:38 +08004024 // apply volume for voip playback after path is set up
4025 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4026 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304027 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4028 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304029 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4030 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004031 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4032 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304033 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004034 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004035 /*
4036 * set custom channel map if:
4037 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4038 * 2. custom channel map has been set by client
4039 * else default channel map of FC/FR/FL can always be set to DSP
4040 */
4041 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4042 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4043 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004044 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4045 adev->dsp_bit_width_enforce_mode,
4046 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004047 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004048 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004049 out->compr = compress_open(adev->snd_card,
4050 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004051 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004052 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304053 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304054 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4055 adev->card_status = CARD_STATUS_OFFLINE;
4056 out->card_status = CARD_STATUS_OFFLINE;
4057 ret = -EIO;
4058 goto error_open;
4059 }
4060
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004061 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004062 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004063 compress_close(out->compr);
4064 out->compr = NULL;
4065 ret = -EIO;
4066 goto error_open;
4067 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304068 /* compress_open sends params of the track, so reset the flag here */
4069 out->is_compr_metadata_avail = false;
4070
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004071 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004072 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004073
Fred Oh3f43e742015-03-04 18:42:34 -08004074 /* Since small bufs uses blocking writes, a write will be blocked
4075 for the default max poll time (20s) in the event of an SSR.
4076 Reduce the poll time to observe and deal with SSR faster.
4077 */
Ashish Jain5106d362016-05-11 19:23:33 +05304078 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004079 compress_set_max_poll_wait(out->compr, 1000);
4080 }
4081
Manish Dewangan69426c82017-01-30 17:35:36 +05304082 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304083 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304084
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004085 audio_extn_dts_create_state_notifier_node(out->usecase);
4086 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4087 popcount(out->channel_mask),
4088 out->playback_started);
4089
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004090#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304091 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004092 audio_extn_dolby_send_ddp_endp_params(adev);
4093#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304094 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4095 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004096 if (adev->visualizer_start_output != NULL)
4097 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4098 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304099 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004100 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004101 }
Derek Chenf13dd492018-11-13 14:53:51 -08004102
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004103 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004104 /* Update cached volume from media to offload/direct stream */
4105 struct listnode *node = NULL;
4106 list_for_each(node, &adev->active_outputs_list) {
4107 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4108 streams_output_ctxt_t,
4109 list);
4110 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4111 out->volume_l = out_ctxt->output->volume_l;
4112 out->volume_r = out_ctxt->output->volume_r;
4113 }
4114 }
4115 out_set_compr_volume(&out->stream,
4116 out->volume_l, out->volume_r);
4117 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004119
4120 if (ret == 0) {
4121 register_out_stream(out);
4122 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004123 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4124 ALOGE("%s: pcm stream not ready", __func__);
4125 goto error_open;
4126 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004127 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004128 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004129 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004130 if (ret < 0)
4131 goto error_open;
4132 }
4133 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004134 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304135 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004136 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004137
vivek mehtad15d2bf2019-05-17 13:35:10 -07004138 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4139 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4140 audio_low_latency_hint_start();
4141 }
4142
Manish Dewangan21a850a2017-08-14 12:03:55 +05304143 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004144 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004145 if (ret < 0)
4146 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4147 }
4148
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004149 // consider a scenario where on pause lower layers are tear down.
4150 // so on resume, swap mixer control need to be sent only when
4151 // backend is active, hence rather than sending from enable device
4152 // sending it from start of streamtream
4153
4154 platform_set_swap_channels(adev, true);
4155
Haynes Mathew George380745d2017-10-04 15:27:45 -07004156 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304157 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004158 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004159error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004160 if (adev->haptic_pcm) {
4161 pcm_close(adev->haptic_pcm);
4162 adev->haptic_pcm = NULL;
4163 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004164 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304165 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004167error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304168 /*
4169 * sleep 50ms to allow sufficient time for kernel
4170 * drivers to recover incases like SSR.
4171 */
4172 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004173error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004174 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304175 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004176 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004177}
4178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004179static int check_input_parameters(uint32_t sample_rate,
4180 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004181 int channel_count,
4182 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004183{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004184 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004185
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304186 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4187 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4188 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004189 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004190 !audio_extn_compr_cap_format_supported(format) &&
4191 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004192 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004193
Aalique Grahame22e49102018-12-18 14:23:57 -08004194 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4195 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4196 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4197 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4198 return -EINVAL;
4199 }
4200
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004201 switch (channel_count) {
4202 case 1:
4203 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304204 case 3:
4205 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004206 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004207 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304208 case 10:
4209 case 12:
4210 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004211 break;
4212 default:
4213 ret = -EINVAL;
4214 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215
4216 switch (sample_rate) {
4217 case 8000:
4218 case 11025:
4219 case 12000:
4220 case 16000:
4221 case 22050:
4222 case 24000:
4223 case 32000:
4224 case 44100:
4225 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004226 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304227 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004228 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304229 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004230 break;
4231 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004232 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004233 }
4234
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004235 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236}
4237
Naresh Tanniru04f71882018-06-26 17:46:22 +05304238
4239/** Add a value in a list if not already present.
4240 * @return true if value was successfully inserted or already present,
4241 * false if the list is full and does not contain the value.
4242 */
4243static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4244 for (size_t i = 0; i < list_length; i++) {
4245 if (list[i] == value) return true; // value is already present
4246 if (list[i] == 0) { // no values in this slot
4247 list[i] = value;
4248 return true; // value inserted
4249 }
4250 }
4251 return false; // could not insert value
4252}
4253
4254/** Add channel_mask in supported_channel_masks if not already present.
4255 * @return true if channel_mask was successfully inserted or already present,
4256 * false if supported_channel_masks is full and does not contain channel_mask.
4257 */
4258static void register_channel_mask(audio_channel_mask_t channel_mask,
4259 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4260 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4261 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4262}
4263
4264/** Add format in supported_formats if not already present.
4265 * @return true if format was successfully inserted or already present,
4266 * false if supported_formats is full and does not contain format.
4267 */
4268static void register_format(audio_format_t format,
4269 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4270 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4271 "%s: stream can not declare supporting its format %x", __func__, format);
4272}
4273/** Add sample_rate in supported_sample_rates if not already present.
4274 * @return true if sample_rate was successfully inserted or already present,
4275 * false if supported_sample_rates is full and does not contain sample_rate.
4276 */
4277static void register_sample_rate(uint32_t sample_rate,
4278 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4279 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4280 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4281}
4282
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004283static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4284{
4285 uint32_t high = num1, low = num2, temp = 0;
4286
4287 if (!num1 || !num2)
4288 return 0;
4289
4290 if (num1 < num2) {
4291 high = num2;
4292 low = num1;
4293 }
4294
4295 while (low != 0) {
4296 temp = low;
4297 low = high % low;
4298 high = temp;
4299 }
4300 return (num1 * num2)/high;
4301}
4302
4303static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4304{
4305 uint32_t remainder = 0;
4306
4307 if (!multiplier)
4308 return num;
4309
4310 remainder = num % multiplier;
4311 if (remainder)
4312 num += (multiplier - remainder);
4313
4314 return num;
4315}
4316
Aalique Grahame22e49102018-12-18 14:23:57 -08004317static size_t get_stream_buffer_size(size_t duration_ms,
4318 uint32_t sample_rate,
4319 audio_format_t format,
4320 int channel_count,
4321 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322{
4323 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004324 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325
Aalique Grahame22e49102018-12-18 14:23:57 -08004326 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004327 if (is_low_latency)
4328 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304329
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004330 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004331 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004332
Ralf Herzbd08d632018-09-28 15:50:49 +02004333 /* make sure the size is multiple of 32 bytes and additionally multiple of
4334 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004335 * At 48 kHz mono 16-bit PCM:
4336 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4337 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004338 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004339 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004340 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004341
4342 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004343}
4344
Aalique Grahame22e49102018-12-18 14:23:57 -08004345static size_t get_input_buffer_size(uint32_t sample_rate,
4346 audio_format_t format,
4347 int channel_count,
4348 bool is_low_latency)
4349{
4350 /* Don't know if USB HIFI in this context so use true to be conservative */
4351 if (check_input_parameters(sample_rate, format, channel_count,
4352 true /*is_usb_hifi */) != 0)
4353 return 0;
4354
4355 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4356 sample_rate,
4357 format,
4358 channel_count,
4359 is_low_latency);
4360}
4361
Derek Chenf6318be2017-06-12 17:16:24 -04004362size_t get_output_period_size(uint32_t sample_rate,
4363 audio_format_t format,
4364 int channel_count,
4365 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304366{
4367 size_t size = 0;
4368 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4369
4370 if ((duration == 0) || (sample_rate == 0) ||
4371 (bytes_per_sample == 0) || (channel_count == 0)) {
4372 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4373 bytes_per_sample, channel_count);
4374 return -EINVAL;
4375 }
4376
4377 size = (sample_rate *
4378 duration *
4379 bytes_per_sample *
4380 channel_count) / 1000;
4381 /*
4382 * To have same PCM samples for all channels, the buffer size requires to
4383 * be multiple of (number of channels * bytes per sample)
4384 * For writes to succeed, the buffer must be written at address which is multiple of 32
4385 */
4386 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4387
4388 return (size/(channel_count * bytes_per_sample));
4389}
4390
Zhou Song48453a02018-01-10 17:50:59 +08004391static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304392{
4393 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004394 uint64_t written_frames = 0;
4395 uint64_t kernel_frames = 0;
4396 uint64_t dsp_frames = 0;
4397 uint64_t signed_frames = 0;
4398 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304399
4400 /* This adjustment accounts for buffering after app processor.
4401 * It is based on estimated DSP latency per use case, rather than exact.
4402 */
Robert Lee58215542019-07-15 20:55:12 +08004403 pthread_mutex_lock(&adev->lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004404 dsp_frames = platform_render_latency(out->dev, out->usecase) *
4405 out->sample_rate / 1000000LL;
Robert Lee58215542019-07-15 20:55:12 +08004406 pthread_mutex_unlock(&adev->lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304407
Zhou Song48453a02018-01-10 17:50:59 +08004408 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004409 written_frames = out->written /
4410 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4411
Ashish Jain5106d362016-05-11 19:23:33 +05304412 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4413 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4414 * hence only estimate.
4415 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004416 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4417 kernel_frames = kernel_buffer_size /
4418 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304419
Weiyin Jiang4813da12020-05-28 00:37:28 +08004420 if (written_frames >= (kernel_frames + dsp_frames))
4421 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304422
Zhou Song48453a02018-01-10 17:50:59 +08004423 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304424 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004425 if (timestamp != NULL )
4426 *timestamp = out->writeAt;
4427 } else if (timestamp != NULL) {
4428 clock_gettime(CLOCK_MONOTONIC, timestamp);
4429 }
4430 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304431
Weiyin Jiang4813da12020-05-28 00:37:28 +08004432 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4433 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304434
4435 return actual_frames_rendered;
4436}
4437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004438static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4439{
4440 struct stream_out *out = (struct stream_out *)stream;
4441
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004442 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004443}
4444
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004445static int out_set_sample_rate(struct audio_stream *stream __unused,
4446 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004447{
4448 return -ENOSYS;
4449}
4450
4451static size_t out_get_buffer_size(const struct audio_stream *stream)
4452{
4453 struct stream_out *out = (struct stream_out *)stream;
4454
Varun Balaraje49253e2017-07-06 19:48:56 +05304455 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304456 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304457 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304458 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4459 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4460 else
4461 return out->compr_config.fragment_size;
4462 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004463 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304464 else if (is_offload_usecase(out->usecase) &&
4465 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304466 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004467
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004468 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004469 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004470}
4471
4472static uint32_t out_get_channels(const struct audio_stream *stream)
4473{
4474 struct stream_out *out = (struct stream_out *)stream;
4475
4476 return out->channel_mask;
4477}
4478
4479static audio_format_t out_get_format(const struct audio_stream *stream)
4480{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004481 struct stream_out *out = (struct stream_out *)stream;
4482
4483 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004484}
4485
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004486static int out_set_format(struct audio_stream *stream __unused,
4487 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004488{
4489 return -ENOSYS;
4490}
4491
4492static int out_standby(struct audio_stream *stream)
4493{
4494 struct stream_out *out = (struct stream_out *)stream;
4495 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004496 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004497
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304498 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4499 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004501 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004502 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004503 if (adev->adm_deregister_stream)
4504 adev->adm_deregister_stream(adev->adm_data, out->handle);
4505
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004506 if (is_offload_usecase(out->usecase))
4507 stop_compressed_output_l(out);
4508
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004509 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004510 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004511 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4512 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304513 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004514 pthread_mutex_unlock(&adev->lock);
4515 pthread_mutex_unlock(&out->lock);
4516 ALOGD("VOIP output entered standby");
4517 return 0;
4518 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004519 if (out->pcm) {
4520 pcm_close(out->pcm);
4521 out->pcm = NULL;
4522 }
Meng Wanga09da002020-04-20 12:56:04 +08004523 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4524 if (adev->haptic_pcm) {
4525 pcm_close(adev->haptic_pcm);
4526 adev->haptic_pcm = NULL;
4527 }
4528
4529 if (adev->haptic_buffer != NULL) {
4530 free(adev->haptic_buffer);
4531 adev->haptic_buffer = NULL;
4532 adev->haptic_buffer_size = 0;
4533 }
4534 adev->haptic_pcm_device_id = 0;
4535 }
4536
Haynes Mathew George16081042017-05-31 17:16:49 -07004537 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4538 do_stop = out->playback_started;
4539 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004540
4541 if (out->mmap_shared_memory_fd >= 0) {
4542 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4543 __func__, out->mmap_shared_memory_fd);
4544 close(out->mmap_shared_memory_fd);
4545 out->mmap_shared_memory_fd = -1;
4546 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004547 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004548 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004549 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304550 out->send_next_track_params = false;
4551 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004552 out->gapless_mdata.encoder_delay = 0;
4553 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004554 if (out->compr != NULL) {
4555 compress_close(out->compr);
4556 out->compr = NULL;
4557 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004558 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004559 if (do_stop) {
4560 stop_output_stream(out);
4561 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304562 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004563 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004564 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565 }
4566 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304567 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004568 return 0;
4569}
4570
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304571static int out_on_error(struct audio_stream *stream)
4572{
4573 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004574 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304575
4576 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004577 // always send CMD_ERROR for offload streams, this
4578 // is needed e.g. when SSR happens within compress_open
4579 // since the stream is active, offload_callback_thread is also active.
4580 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4581 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004582 }
4583 pthread_mutex_unlock(&out->lock);
4584
4585 status = out_standby(&out->stream.common);
4586
4587 lock_output_stream(out);
4588 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004589 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304590 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304591
4592 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4593 ALOGD("Setting previous card status if offline");
4594 out->prev_card_status_offline = true;
4595 }
4596
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304597 pthread_mutex_unlock(&out->lock);
4598
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004599 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304600}
4601
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304602/*
4603 *standby implementation without locks, assumes that the callee already
4604 *has taken adev and out lock.
4605 */
4606int out_standby_l(struct audio_stream *stream)
4607{
4608 struct stream_out *out = (struct stream_out *)stream;
4609 struct audio_device *adev = out->dev;
4610
4611 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4612 stream, out->usecase, use_case_table[out->usecase]);
4613
4614 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004615 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304616 if (adev->adm_deregister_stream)
4617 adev->adm_deregister_stream(adev->adm_data, out->handle);
4618
4619 if (is_offload_usecase(out->usecase))
4620 stop_compressed_output_l(out);
4621
4622 out->standby = true;
4623 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4624 voice_extn_compress_voip_close_output_stream(stream);
4625 out->started = 0;
4626 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004627 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304628 return 0;
4629 } else if (!is_offload_usecase(out->usecase)) {
4630 if (out->pcm) {
4631 pcm_close(out->pcm);
4632 out->pcm = NULL;
4633 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004634 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4635 if (adev->haptic_pcm) {
4636 pcm_close(adev->haptic_pcm);
4637 adev->haptic_pcm = NULL;
4638 }
4639
4640 if (adev->haptic_buffer != NULL) {
4641 free(adev->haptic_buffer);
4642 adev->haptic_buffer = NULL;
4643 adev->haptic_buffer_size = 0;
4644 }
4645 adev->haptic_pcm_device_id = 0;
4646 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304647 } else {
4648 ALOGD("copl(%p):standby", out);
4649 out->send_next_track_params = false;
4650 out->is_compr_metadata_avail = false;
4651 out->gapless_mdata.encoder_delay = 0;
4652 out->gapless_mdata.encoder_padding = 0;
4653 if (out->compr != NULL) {
4654 compress_close(out->compr);
4655 out->compr = NULL;
4656 }
4657 }
4658 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004659 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304660 }
4661 ALOGD("%s: exit", __func__);
4662 return 0;
4663}
4664
Aalique Grahame22e49102018-12-18 14:23:57 -08004665static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666{
Aalique Grahame22e49102018-12-18 14:23:57 -08004667 struct stream_out *out = (struct stream_out *)stream;
4668
4669 // We try to get the lock for consistency,
4670 // but it isn't necessary for these variables.
4671 // If we're not in standby, we may be blocked on a write.
4672 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4673 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4674 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4675
Andy Hunga1f48fa2019-07-01 18:14:53 -07004676 char buffer[256]; // for statistics formatting
4677 if (!is_offload_usecase(out->usecase)) {
4678 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4679 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4680 }
4681
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004682 if (out->start_latency_ms.n > 0) {
4683 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4684 dprintf(fd, " Start latency ms: %s\n", buffer);
4685 }
4686
Aalique Grahame22e49102018-12-18 14:23:57 -08004687 if (locked) {
4688 pthread_mutex_unlock(&out->lock);
4689 }
4690
4691 // dump error info
4692 (void)error_log_dump(
4693 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004695 return 0;
4696}
4697
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004698static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4699{
4700 int ret = 0;
4701 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004702
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004703 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004704 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004705 return -EINVAL;
4706 }
4707
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304708 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004709
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004710 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4711 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304712 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004713 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004714 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4715 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304716 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004717 }
4718
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004719 ALOGV("%s new encoder delay %u and padding %u", __func__,
4720 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4721
4722 return 0;
4723}
4724
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004725static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4726{
4727 return out == adev->primary_output || out == adev->voice_tx_output;
4728}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004729
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304730// note: this call is safe only if the stream_cb is
4731// removed first in close_output_stream (as is done now).
4732static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4733{
4734 if (!stream || !parms)
4735 return;
4736
4737 struct stream_out *out = (struct stream_out *)stream;
4738 struct audio_device *adev = out->dev;
4739
4740 card_status_t status;
4741 int card;
4742 if (parse_snd_card_status(parms, &card, &status) < 0)
4743 return;
4744
4745 pthread_mutex_lock(&adev->lock);
4746 bool valid_cb = (card == adev->snd_card);
4747 pthread_mutex_unlock(&adev->lock);
4748
4749 if (!valid_cb)
4750 return;
4751
4752 lock_output_stream(out);
4753 if (out->card_status != status)
4754 out->card_status = status;
4755 pthread_mutex_unlock(&out->lock);
4756
4757 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4758 use_case_table[out->usecase],
4759 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4760
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304761 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304762 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304763 if (voice_is_call_state_active(adev) &&
4764 out == adev->primary_output) {
4765 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4766 pthread_mutex_lock(&adev->lock);
4767 voice_stop_call(adev);
4768 adev->mode = AUDIO_MODE_NORMAL;
4769 pthread_mutex_unlock(&adev->lock);
4770 }
4771 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304772 return;
4773}
4774
Kevin Rocardfce19002017-08-07 19:21:36 -07004775static int get_alive_usb_card(struct str_parms* parms) {
4776 int card;
4777 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4778 !audio_extn_usb_alive(card)) {
4779 return card;
4780 }
4781 return -ENODEV;
4782}
4783
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004784int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004785 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004786{
4787 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004788 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004789 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004790 bool bypass_a2dp = false;
4791 bool reconfig = false;
4792 unsigned long service_interval = 0;
4793
4794 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004795 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4796
4797 list_init(&new_devices);
4798 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004799
4800 lock_output_stream(out);
4801 pthread_mutex_lock(&adev->lock);
4802
4803 /*
4804 * When HDMI cable is unplugged the music playback is paused and
4805 * the policy manager sends routing=0. But the audioflinger continues
4806 * to write data until standby time (3sec). As the HDMI core is
4807 * turned off, the write gets blocked.
4808 * Avoid this by routing audio to speaker until standby.
4809 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004810 if (is_single_device_type_equal(&out->device_list,
4811 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004812 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004813 !audio_extn_passthru_is_passthrough_stream(out) &&
4814 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004815 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004816 }
4817 /*
4818 * When A2DP is disconnected the
4819 * music playback is paused and the policy manager sends routing=0
4820 * But the audioflinger continues to write data until standby time
4821 * (3sec). As BT is turned off, the write gets blocked.
4822 * Avoid this by routing audio to speaker until standby.
4823 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004824 if (is_a2dp_out_device_type(&out->device_list) &&
4825 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004826 !audio_extn_a2dp_source_is_ready() &&
4827 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004828 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004829 }
4830 /*
4831 * When USB headset is disconnected the music platback paused
4832 * and the policy manager send routing=0. But if the USB is connected
4833 * back before the standby time, AFE is not closed and opened
4834 * when USB is connected back. So routing to speker will guarantee
4835 * AFE reconfiguration and AFE will be opend once USB is connected again
4836 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004837 if (is_usb_out_device_type(&out->device_list) &&
4838 list_empty(&new_devices) &&
4839 !audio_extn_usb_connected(NULL)) {
4840 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4841 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004842 /* To avoid a2dp to sco overlapping / BT device improper state
4843 * check with BT lib about a2dp streaming support before routing
4844 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004845 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004846 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004847 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4848 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004849 //combo usecase just by pass a2dp
4850 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4851 bypass_a2dp = true;
4852 } else {
4853 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4854 /* update device to a2dp and don't route as BT returned error
4855 * However it is still possible a2dp routing called because
4856 * of current active device disconnection (like wired headset)
4857 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004858 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004859 pthread_mutex_unlock(&adev->lock);
4860 pthread_mutex_unlock(&out->lock);
4861 goto error;
4862 }
4863 }
4864 }
4865
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004866 // Workaround: If routing to an non existing usb device, fail gracefully
4867 // The routing request will otherwise block during 10 second
4868 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004869 if (is_usb_out_device_type(&new_devices)) {
4870 struct str_parms *parms =
4871 str_parms_create_str(get_usb_device_address(&new_devices));
4872 if (!parms)
4873 goto error;
4874 if ((card = get_alive_usb_card(parms)) >= 0) {
4875 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4876 pthread_mutex_unlock(&adev->lock);
4877 pthread_mutex_unlock(&out->lock);
4878 str_parms_destroy(parms);
4879 ret = -ENOSYS;
4880 goto error;
4881 }
4882 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004883 }
4884
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004885 // Workaround: If routing to an non existing hdmi device, fail gracefully
4886 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4887 (platform_get_edid_info_v2(adev->platform,
4888 out->extconn.cs.controller,
4889 out->extconn.cs.stream) != 0)) {
4890 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4891 pthread_mutex_unlock(&adev->lock);
4892 pthread_mutex_unlock(&out->lock);
4893 ret = -ENOSYS;
4894 goto error;
4895 }
4896
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004897 /*
4898 * select_devices() call below switches all the usecases on the same
4899 * backend to the new device. Refer to check_usecases_codec_backend() in
4900 * the select_devices(). But how do we undo this?
4901 *
4902 * For example, music playback is active on headset (deep-buffer usecase)
4903 * and if we go to ringtones and select a ringtone, low-latency usecase
4904 * will be started on headset+speaker. As we can't enable headset+speaker
4905 * and headset devices at the same time, select_devices() switches the music
4906 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4907 * So when the ringtone playback is completed, how do we undo the same?
4908 *
4909 * We are relying on the out_set_parameters() call on deep-buffer output,
4910 * once the ringtone playback is ended.
4911 * NOTE: We should not check if the current devices are same as new devices.
4912 * Because select_devices() must be called to switch back the music
4913 * playback to headset.
4914 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004915 if (!list_empty(&new_devices)) {
4916 bool same_dev = compare_devices(&out->device_list, &new_devices);
4917 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004918
4919 if (output_drives_call(adev, out)) {
4920 if (!voice_is_call_state_active(adev)) {
4921 if (adev->mode == AUDIO_MODE_IN_CALL) {
4922 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004923 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004924 service_interval =
4925 audio_extn_usb_find_service_interval(true, true /*playback*/);
4926 audio_extn_usb_set_service_interval(true /*playback*/,
4927 service_interval,
4928 &reconfig);
4929 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4930 }
4931 ret = voice_start_call(adev);
4932 }
4933 } else {
4934 adev->current_call_output = out;
4935 voice_update_devices_for_all_voice_usecases(adev);
4936 }
4937 }
4938
4939 if (!out->standby) {
4940 if (!same_dev) {
4941 ALOGV("update routing change");
4942 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4943 adev->perf_lock_opts,
4944 adev->perf_lock_opts_size);
4945 if (adev->adm_on_routing_change)
4946 adev->adm_on_routing_change(adev->adm_data,
4947 out->handle);
4948 }
4949 if (!bypass_a2dp) {
4950 select_devices(adev, out->usecase);
4951 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004952 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4953 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004954 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004955 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004956 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004957 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004958 }
4959
4960 if (!same_dev) {
4961 // on device switch force swap, lower functions will make sure
4962 // to check if swap is allowed or not.
4963 platform_set_swap_channels(adev, true);
4964 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4965 }
4966 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4967 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004968 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004969 pthread_mutex_lock(&out->compr_mute_lock);
4970 out->a2dp_compress_mute = false;
4971 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4972 pthread_mutex_unlock(&out->compr_mute_lock);
4973 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4974 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4975 }
4976 }
4977 }
4978
4979 pthread_mutex_unlock(&adev->lock);
4980 pthread_mutex_unlock(&out->lock);
4981
4982 /*handles device and call state changes*/
4983 audio_extn_extspk_update(adev->extspk);
4984
4985error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004986 ALOGV("%s: exit: code(%d)", __func__, ret);
4987 return ret;
4988}
4989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004990static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4991{
4992 struct stream_out *out = (struct stream_out *)stream;
4993 struct audio_device *adev = out->dev;
4994 struct str_parms *parms;
4995 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004996 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004997 int ext_controller = -1;
4998 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004999
sangwoobc677242013-08-08 16:53:43 +09005000 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005001 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005002 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305003 if (!parms)
5004 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005005
5006 err = platform_get_controller_stream_from_params(parms, &ext_controller,
5007 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08005008 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005009 out->extconn.cs.controller = ext_controller;
5010 out->extconn.cs.stream = ext_stream;
5011 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5012 use_case_table[out->usecase], out->extconn.cs.controller,
5013 out->extconn.cs.stream);
5014 }
5015
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005016 if (out == adev->primary_output) {
5017 pthread_mutex_lock(&adev->lock);
5018 audio_extn_set_parameters(adev, parms);
5019 pthread_mutex_unlock(&adev->lock);
5020 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005021 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005022 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005023 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005024
5025 audio_extn_dts_create_state_notifier_node(out->usecase);
5026 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5027 popcount(out->channel_mask),
5028 out->playback_started);
5029
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005030 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005031 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005032
Surendar Karkaf51b5842018-04-26 11:28:38 +05305033 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5034 sizeof(value));
5035 if (err >= 0) {
5036 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5037 audio_extn_send_dual_mono_mixing_coefficients(out);
5038 }
5039
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305040 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5041 if (err >= 0) {
5042 strlcpy(out->profile, value, sizeof(out->profile));
5043 ALOGV("updating stream profile with value '%s'", out->profile);
5044 lock_output_stream(out);
5045 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5046 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005047 &out->device_list, out->flags,
5048 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305049 out->sample_rate, out->bit_width,
5050 out->channel_mask, out->profile,
5051 &out->app_type_cfg);
5052 pthread_mutex_unlock(&out->lock);
5053 }
5054
Alexy Joseph98988832017-01-13 14:56:59 -08005055 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005056 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5057 // and vendor.audio.hal.output.suspend.supported is set to true
5058 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005059 //check suspend parameter only for low latency and if the property
5060 //is enabled
5061 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5062 ALOGI("%s: got suspend_playback %s", __func__, value);
5063 lock_output_stream(out);
5064 if (!strncmp(value, "false", 5)) {
5065 //suspend_playback=false is supposed to set QOS value back to 75%
5066 //the mixer control sent with value Enable will achieve that
5067 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5068 } else if (!strncmp (value, "true", 4)) {
5069 //suspend_playback=true is supposed to remove QOS value
5070 //resetting the mixer control will set the default value
5071 //for the mixer control which is Disable and this removes the QOS vote
5072 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5073 } else {
5074 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5075 " got %s", __func__, value);
5076 ret = -1;
5077 }
5078
5079 if (ret != 0) {
5080 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5081 __func__, out->pm_qos_mixer_path, ret);
5082 }
5083
5084 pthread_mutex_unlock(&out->lock);
5085 }
5086 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005087
Alexy Joseph98988832017-01-13 14:56:59 -08005088 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005089 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305090error:
Eric Laurent994a6932013-07-17 11:51:42 -07005091 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005092 return ret;
5093}
5094
Paul McLeana50b7332018-12-17 08:24:21 -07005095static int in_set_microphone_direction(const struct audio_stream_in *stream,
5096 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005097 struct stream_in *in = (struct stream_in *)stream;
5098
5099 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5100
5101 in->direction = dir;
5102
5103 if (in->standby)
5104 return 0;
5105
5106 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005107}
5108
5109static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005110 struct stream_in *in = (struct stream_in *)stream;
5111
5112 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5113
5114 if (zoom > 1.0 || zoom < -1.0)
5115 return -EINVAL;
5116
5117 in->zoom = zoom;
5118
5119 if (in->standby)
5120 return 0;
5121
5122 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005123}
5124
5125
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005126static bool stream_get_parameter_channels(struct str_parms *query,
5127 struct str_parms *reply,
5128 audio_channel_mask_t *supported_channel_masks) {
5129 int ret = -1;
5130 char value[512];
5131 bool first = true;
5132 size_t i, j;
5133
5134 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5135 ret = 0;
5136 value[0] = '\0';
5137 i = 0;
5138 while (supported_channel_masks[i] != 0) {
5139 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5140 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5141 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305142 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005143
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305144 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005145 first = false;
5146 break;
5147 }
5148 }
5149 i++;
5150 }
5151 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5152 }
5153 return ret == 0;
5154}
5155
5156static bool stream_get_parameter_formats(struct str_parms *query,
5157 struct str_parms *reply,
5158 audio_format_t *supported_formats) {
5159 int ret = -1;
5160 char value[256];
5161 size_t i, j;
5162 bool first = true;
5163
5164 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5165 ret = 0;
5166 value[0] = '\0';
5167 i = 0;
5168 while (supported_formats[i] != 0) {
5169 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5170 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5171 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305172 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005173 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305174 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005175 first = false;
5176 break;
5177 }
5178 }
5179 i++;
5180 }
5181 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5182 }
5183 return ret == 0;
5184}
5185
5186static bool stream_get_parameter_rates(struct str_parms *query,
5187 struct str_parms *reply,
5188 uint32_t *supported_sample_rates) {
5189
5190 int i;
5191 char value[256];
5192 int ret = -1;
5193 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5194 ret = 0;
5195 value[0] = '\0';
5196 i=0;
5197 int cursor = 0;
5198 while (supported_sample_rates[i]) {
5199 int avail = sizeof(value) - cursor;
5200 ret = snprintf(value + cursor, avail, "%s%d",
5201 cursor > 0 ? "|" : "",
5202 supported_sample_rates[i]);
5203 if (ret < 0 || ret >= avail) {
5204 // if cursor is at the last element of the array
5205 // overwrite with \0 is duplicate work as
5206 // snprintf already put a \0 in place.
5207 // else
5208 // we had space to write the '|' at value[cursor]
5209 // (which will be overwritten) or no space to fill
5210 // the first element (=> cursor == 0)
5211 value[cursor] = '\0';
5212 break;
5213 }
5214 cursor += ret;
5215 ++i;
5216 }
5217 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5218 value);
5219 }
5220 return ret >= 0;
5221}
5222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005223static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5224{
5225 struct stream_out *out = (struct stream_out *)stream;
5226 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005227 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005228 char value[256];
5229 struct str_parms *reply = str_parms_create();
5230 size_t i, j;
5231 int ret;
5232 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005233
5234 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005235 if (reply) {
5236 str_parms_destroy(reply);
5237 }
5238 if (query) {
5239 str_parms_destroy(query);
5240 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005241 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5242 return NULL;
5243 }
5244
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005245 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005246 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5247 if (ret >= 0) {
5248 value[0] = '\0';
5249 i = 0;
5250 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005251 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5252 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005253 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005254 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005255 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005256 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005257 first = false;
5258 break;
5259 }
5260 }
5261 i++;
5262 }
5263 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5264 str = str_parms_to_str(reply);
5265 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005266 voice_extn_out_get_parameters(out, query, reply);
5267 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005268 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005269
Alexy Joseph62142aa2015-11-16 15:10:34 -08005270
5271 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5272 if (ret >= 0) {
5273 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305274 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5275 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005276 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305277 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005278 } else {
5279 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305280 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005281 }
5282 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005283 if (str)
5284 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005285 str = str_parms_to_str(reply);
5286 }
5287
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005288 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5289 if (ret >= 0) {
5290 value[0] = '\0';
5291 i = 0;
5292 first = true;
5293 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005294 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5295 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005296 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005297 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005298 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005299 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005300 first = false;
5301 break;
5302 }
5303 }
5304 i++;
5305 }
5306 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005307 if (str)
5308 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005309 str = str_parms_to_str(reply);
5310 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005311
5312 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5313 if (ret >= 0) {
5314 value[0] = '\0';
5315 i = 0;
5316 first = true;
5317 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005318 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5319 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005320 if (!first) {
5321 strlcat(value, "|", sizeof(value));
5322 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005323 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005324 first = false;
5325 break;
5326 }
5327 }
5328 i++;
5329 }
5330 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5331 if (str)
5332 free(str);
5333 str = str_parms_to_str(reply);
5334 }
5335
Alexy Joseph98988832017-01-13 14:56:59 -08005336 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5337 //only low latency track supports suspend_resume
5338 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005339 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005340 if (str)
5341 free(str);
5342 str = str_parms_to_str(reply);
5343 }
5344
5345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005346 str_parms_destroy(query);
5347 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005348 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005349 return str;
5350}
5351
5352static uint32_t out_get_latency(const struct audio_stream_out *stream)
5353{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005354 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005355 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005356 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005357
Alexy Josephaa54c872014-12-03 02:46:47 -08005358 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305359 lock_output_stream(out);
5360 latency = audio_extn_utils_compress_get_dsp_latency(out);
5361 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005362 } else if ((out->realtime) ||
5363 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005364 // since the buffer won't be filled up faster than realtime,
5365 // return a smaller number
5366 if (out->config.rate)
5367 period_ms = (out->af_period_multiplier * out->config.period_size *
5368 1000) / (out->config.rate);
5369 else
5370 period_ms = 0;
Robert Lee58215542019-07-15 20:55:12 +08005371 pthread_mutex_lock(&adev->lock);
5372 latency = period_ms + platform_render_latency(out->dev, out->usecase)/1000;
5373 pthread_mutex_unlock(&adev->lock);
Alexy Josephaa54c872014-12-03 02:46:47 -08005374 } else {
5375 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005376 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005377 }
5378
Zhou Songd2537a02020-06-11 22:04:46 +08005379 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005380 latency += audio_extn_a2dp_get_encoder_latency();
5381
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305382 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005383 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005384}
5385
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305386static float AmpToDb(float amplification)
5387{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305388 float db = DSD_VOLUME_MIN_DB;
5389 if (amplification > 0) {
5390 db = 20 * log10(amplification);
5391 if(db < DSD_VOLUME_MIN_DB)
5392 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305393 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305394 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305395}
5396
Arun Mirpuri5d170872019-03-26 13:21:31 -07005397static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5398 float right)
5399{
5400 struct stream_out *out = (struct stream_out *)stream;
5401 long volume = 0;
5402 char mixer_ctl_name[128] = "";
5403 struct audio_device *adev = out->dev;
5404 struct mixer_ctl *ctl = NULL;
5405 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5406 PCM_PLAYBACK);
5407
5408 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5409 "Playback %d Volume", pcm_device_id);
5410 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5411 if (!ctl) {
5412 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5413 __func__, mixer_ctl_name);
5414 return -EINVAL;
5415 }
5416 if (left != right)
5417 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5418 __func__, left, right);
5419 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5420 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5421 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5422 __func__, mixer_ctl_name, volume);
5423 return -EINVAL;
5424 }
5425 return 0;
5426}
5427
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305428static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5429 float right)
5430{
5431 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305432 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305433 char mixer_ctl_name[128];
5434 struct audio_device *adev = out->dev;
5435 struct mixer_ctl *ctl;
5436 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5437 PCM_PLAYBACK);
5438
5439 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5440 "Compress Playback %d Volume", pcm_device_id);
5441 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5442 if (!ctl) {
5443 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5444 __func__, mixer_ctl_name);
5445 return -EINVAL;
5446 }
5447 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5448 __func__, mixer_ctl_name, left, right);
5449 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5450 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5451 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5452
5453 return 0;
5454}
5455
Zhou Song2b8f28f2017-09-11 10:51:38 +08005456static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5457 float right)
5458{
5459 struct stream_out *out = (struct stream_out *)stream;
5460 char mixer_ctl_name[] = "App Type Gain";
5461 struct audio_device *adev = out->dev;
5462 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305463 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005464
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005465 if (!is_valid_volume(left, right)) {
5466 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5467 __func__, left, right);
5468 return -EINVAL;
5469 }
5470
Zhou Song2b8f28f2017-09-11 10:51:38 +08005471 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5472 if (!ctl) {
5473 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5474 __func__, mixer_ctl_name);
5475 return -EINVAL;
5476 }
5477
5478 set_values[0] = 0; //0: Rx Session 1:Tx Session
5479 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305480 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5481 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005482
5483 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5484 return 0;
5485}
5486
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305487static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5488 float right)
5489{
5490 struct stream_out *out = (struct stream_out *)stream;
5491 /* Volume control for pcm playback */
5492 if (left != right) {
5493 return -EINVAL;
5494 } else {
5495 char mixer_ctl_name[128];
5496 struct audio_device *adev = out->dev;
5497 struct mixer_ctl *ctl;
5498 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5499 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5500 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5501 if (!ctl) {
5502 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5503 return -EINVAL;
5504 }
5505
5506 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5507 int ret = mixer_ctl_set_value(ctl, 0, volume);
5508 if (ret < 0) {
5509 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5510 return -EINVAL;
5511 }
5512
5513 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5514
5515 return 0;
5516 }
5517}
5518
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005519static int out_set_volume(struct audio_stream_out *stream, float left,
5520 float right)
5521{
Eric Laurenta9024de2013-04-04 09:19:12 -07005522 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005523 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305524 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005525
Arun Mirpuri5d170872019-03-26 13:21:31 -07005526 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005527 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5528 /* only take left channel into account: the API is for stereo anyway */
5529 out->muted = (left == 0.0f);
5530 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005531 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305532 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005533 /*
5534 * Set mute or umute on HDMI passthrough stream.
5535 * Only take left channel into account.
5536 * Mute is 0 and unmute 1
5537 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305538 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305539 } else if (out->format == AUDIO_FORMAT_DSD){
5540 char mixer_ctl_name[128] = "DSD Volume";
5541 struct audio_device *adev = out->dev;
5542 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5543
5544 if (!ctl) {
5545 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5546 __func__, mixer_ctl_name);
5547 return -EINVAL;
5548 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305549 volume[0] = (long)(AmpToDb(left));
5550 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305551 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5552 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005553 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005554 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005555 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5556 struct listnode *node = NULL;
5557 list_for_each(node, &adev->active_outputs_list) {
5558 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5559 streams_output_ctxt_t,
5560 list);
5561 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5562 out->volume_l = out_ctxt->output->volume_l;
5563 out->volume_r = out_ctxt->output->volume_r;
5564 }
5565 }
5566 if (!out->a2dp_compress_mute) {
5567 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5568 }
5569 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005570 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305571 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005572 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305573 if (!out->a2dp_compress_mute)
5574 ret = out_set_compr_volume(stream, left, right);
5575 out->volume_l = left;
5576 out->volume_r = right;
5577 pthread_mutex_unlock(&out->compr_mute_lock);
5578 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005579 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005580 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005581 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5582 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5583 if (!out->standby) {
5584 audio_extn_utils_send_app_type_gain(out->dev,
5585 out->app_type_cfg.app_type,
5586 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005587 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005588 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005589 out->volume_l = left;
5590 out->volume_r = right;
5591 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005592 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5593 ALOGV("%s: MMAP set volume called", __func__);
5594 if (!out->standby)
5595 ret = out_set_mmap_volume(stream, left, right);
5596 out->volume_l = left;
5597 out->volume_r = right;
5598 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305599 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305600 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5601 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305602 /* Volume control for pcm playback */
5603 if (!out->standby)
5604 ret = out_set_pcm_volume(stream, left, right);
5605 else
5606 out->apply_volume = true;
5607
5608 out->volume_l = left;
5609 out->volume_r = right;
5610 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005611 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5612 ALOGV("%s: bus device set volume called", __func__);
5613 if (!out->standby)
5614 ret = out_set_pcm_volume(stream, left, right);
5615 out->volume_l = left;
5616 out->volume_r = right;
5617 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005618 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005620 return -ENOSYS;
5621}
5622
Zhou Songc9672822017-08-16 16:01:39 +08005623static void update_frames_written(struct stream_out *out, size_t bytes)
5624{
5625 size_t bpf = 0;
5626
5627 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5628 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5629 bpf = 1;
5630 else if (!is_offload_usecase(out->usecase))
5631 bpf = audio_bytes_per_sample(out->format) *
5632 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005633
5634 pthread_mutex_lock(&out->position_query_lock);
5635 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005636 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005637 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5638 }
5639 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005640}
5641
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005642int split_and_write_audio_haptic_data(struct stream_out *out,
5643 const void *buffer, size_t bytes_to_write)
5644{
5645 struct audio_device *adev = out->dev;
5646
5647 int ret = 0;
5648 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5649 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5650 size_t frame_size = channel_count * bytes_per_sample;
5651 size_t frame_count = bytes_to_write / frame_size;
5652
5653 bool force_haptic_path =
5654 property_get_bool("vendor.audio.test_haptic", false);
5655
5656 // extract Haptics data from Audio buffer
5657 bool alloc_haptic_buffer = false;
5658 int haptic_channel_count = adev->haptics_config.channels;
5659 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5660 size_t audio_frame_size = frame_size - haptic_frame_size;
5661 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5662
5663 if (adev->haptic_buffer == NULL) {
5664 alloc_haptic_buffer = true;
5665 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5666 free(adev->haptic_buffer);
5667 adev->haptic_buffer_size = 0;
5668 alloc_haptic_buffer = true;
5669 }
5670
5671 if (alloc_haptic_buffer) {
5672 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005673 if(adev->haptic_buffer == NULL) {
5674 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5675 return -ENOMEM;
5676 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005677 adev->haptic_buffer_size = total_haptic_buffer_size;
5678 }
5679
5680 size_t src_index = 0, aud_index = 0, hap_index = 0;
5681 uint8_t *audio_buffer = (uint8_t *)buffer;
5682 uint8_t *haptic_buffer = adev->haptic_buffer;
5683
5684 // This is required for testing only. This works for stereo data only.
5685 // One channel is fed to audio stream and other to haptic stream for testing.
5686 if (force_haptic_path)
5687 audio_frame_size = haptic_frame_size = bytes_per_sample;
5688
5689 for (size_t i = 0; i < frame_count; i++) {
5690 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5691 audio_frame_size);
5692 aud_index += audio_frame_size;
5693 src_index += audio_frame_size;
5694
5695 if (adev->haptic_pcm)
5696 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5697 haptic_frame_size);
5698 hap_index += haptic_frame_size;
5699 src_index += haptic_frame_size;
5700
5701 // This is required for testing only.
5702 // Discard haptic channel data.
5703 if (force_haptic_path)
5704 src_index += haptic_frame_size;
5705 }
5706
5707 // write to audio pipeline
5708 ret = pcm_write(out->pcm, (void *)audio_buffer,
5709 frame_count * audio_frame_size);
5710
5711 // write to haptics pipeline
5712 if (adev->haptic_pcm)
5713 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5714 frame_count * haptic_frame_size);
5715
5716 return ret;
5717}
5718
Aalique Grahame22e49102018-12-18 14:23:57 -08005719#ifdef NO_AUDIO_OUT
5720static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5721 const void *buffer __unused, size_t bytes)
5722{
5723 struct stream_out *out = (struct stream_out *)stream;
5724
5725 /* No Output device supported other than BT for playback.
5726 * Sleep for the amount of buffer duration
5727 */
5728 lock_output_stream(out);
5729 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5730 (const struct audio_stream_out *)&out->stream) /
5731 out_get_sample_rate(&out->stream.common));
5732 pthread_mutex_unlock(&out->lock);
5733 return bytes;
5734}
5735#endif
5736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005737static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5738 size_t bytes)
5739{
5740 struct stream_out *out = (struct stream_out *)stream;
5741 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005742 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305743 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005744 const size_t frame_size = audio_stream_out_frame_size(stream);
5745 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305746 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005747 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005748
Haynes Mathew George380745d2017-10-04 15:27:45 -07005749 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005750 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305751
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305752 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005753
Dhananjay Kumarac341582017-02-23 23:42:25 +05305754 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305755 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305756 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5757 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005758 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305759 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305760 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305761 ALOGD(" %s: sound card is not active/SSR state", __func__);
5762 ret= -EIO;
5763 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305764 }
5765 }
5766
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305767 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305768 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305769 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305770 goto exit;
5771 }
5772
Haynes Mathew George16081042017-05-31 17:16:49 -07005773 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5774 ret = -EINVAL;
5775 goto exit;
5776 }
5777
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005778 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305779 !out->is_iec61937_info_available) {
5780
5781 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5782 out->is_iec61937_info_available = true;
5783 } else if (audio_extn_passthru_is_enabled()) {
5784 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305785 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305786
5787 if((out->format == AUDIO_FORMAT_DTS) ||
5788 (out->format == AUDIO_FORMAT_DTS_HD)) {
5789 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5790 buffer, bytes);
5791 if (ret) {
5792 if (ret != -ENOSYS) {
5793 out->is_iec61937_info_available = false;
5794 ALOGD("iec61937 transmission info not yet updated retry");
5795 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305796 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305797 /* if stream has started and after that there is
5798 * stream config change (iec transmission config)
5799 * then trigger select_device to update backend configuration.
5800 */
5801 out->stream_config_changed = true;
5802 pthread_mutex_lock(&adev->lock);
5803 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305804 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005805 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305806 ret = -EINVAL;
5807 goto exit;
5808 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305809 pthread_mutex_unlock(&adev->lock);
5810 out->stream_config_changed = false;
5811 out->is_iec61937_info_available = true;
5812 }
5813 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305814
Meng Wang4c32fb42020-01-16 17:57:11 +08005815#ifdef AUDIO_GKI_ENABLED
5816 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5817 compr_passthr = out->compr_config.codec->reserved[0];
5818#else
5819 compr_passthr = out->compr_config.codec->compr_passthr;
5820#endif
5821
Garmond Leung317cbf12017-09-13 16:20:50 -07005822 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005823 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305824 (out->is_iec61937_info_available == true)) {
5825 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5826 ret = -EINVAL;
5827 goto exit;
5828 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305829 }
5830 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305831
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005832 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005833 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005834 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5835 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305836 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305837 ret = -EIO;
5838 goto exit;
5839 }
5840 }
5841 }
5842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005843 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005844 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005845 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5846
Eric Laurent150dbfe2013-02-27 14:31:02 -08005847 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005848 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5849 ret = voice_extn_compress_voip_start_output_stream(out);
5850 else
5851 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005852 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005853 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005854 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005855 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005856 goto exit;
5857 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305858 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005859 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
vivek mehtab72d08d2016-04-29 03:16:47 -07005860 if (last_known_cal_step != -1) {
5861 ALOGD("%s: retry previous failed cal level set", __func__);
5862 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305863 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005864 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305865
5866 if ((out->is_iec61937_info_available == true) &&
5867 (audio_extn_passthru_is_passthrough_stream(out))&&
5868 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5869 ret = -EINVAL;
5870 goto exit;
5871 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305872 if (out->set_dual_mono)
5873 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005874
5875 // log startup time in ms.
5876 simple_stats_log(
5877 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005878 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005879
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005880 if (adev->is_channel_status_set == false &&
5881 compare_device_type(&out->device_list,
5882 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005883 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305884 adev->is_channel_status_set = true;
5885 }
5886
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305887 if ((adev->use_old_pspd_mix_ctrl == true) &&
5888 (out->pspd_coeff_sent == false)) {
5889 /*
5890 * Need to resend pspd coefficients after stream started for
5891 * older kernel version as it does not save the coefficients
5892 * and also stream has to be started for coeff to apply.
5893 */
5894 usecase = get_usecase_from_list(adev, out->usecase);
5895 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305896 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305897 out->pspd_coeff_sent = true;
5898 }
5899 }
5900
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005901 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005902 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005903 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005904 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005905 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5906 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305907 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5908 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005909 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305910 out->send_next_track_params = false;
5911 out->is_compr_metadata_avail = false;
5912 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005913 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305914 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305915 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005916
Ashish Jain83a6cc22016-06-28 14:34:17 +05305917 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305918 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305919 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305920 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005921 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305922 return -EINVAL;
5923 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305924 audio_format_t dst_format = out->hal_op_format;
5925 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305926
Dieter Luecking5d57def2018-09-07 14:23:37 +02005927 /* prevent division-by-zero */
5928 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5929 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5930 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5931 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305932 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005933 ATRACE_END();
5934 return -EINVAL;
5935 }
5936
Ashish Jainf1eaa582016-05-23 20:54:24 +05305937 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5938 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5939
Ashish Jain83a6cc22016-06-28 14:34:17 +05305940 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305941 dst_format,
5942 buffer,
5943 src_format,
5944 frames);
5945
Ashish Jain83a6cc22016-06-28 14:34:17 +05305946 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305947 bytes_to_write);
5948
5949 /*Convert written bytes in audio flinger format*/
5950 if (ret > 0)
5951 ret = ((ret * format_to_bitwidth_table[out->format]) /
5952 format_to_bitwidth_table[dst_format]);
5953 }
5954 } else
5955 ret = compress_write(out->compr, buffer, bytes);
5956
Zhou Songc9672822017-08-16 16:01:39 +08005957 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5958 update_frames_written(out, bytes);
5959
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305960 if (ret < 0)
5961 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005962 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305963 /*msg to cb thread only if non blocking write is enabled*/
5964 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305965 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005966 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305967 } else if (-ENETRESET == ret) {
5968 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305969 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305970 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305971 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005972 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305973 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005974 }
Ashish Jain5106d362016-05-11 19:23:33 +05305975
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305976 /* Call compr start only when non-zero bytes of data is there to be rendered */
5977 if (!out->playback_started && ret > 0) {
5978 int status = compress_start(out->compr);
5979 if (status < 0) {
5980 ret = status;
5981 ALOGE("%s: compr start failed with err %d", __func__, errno);
5982 goto exit;
5983 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005984 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005985 out->playback_started = 1;
5986 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005987
5988 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5989 popcount(out->channel_mask),
5990 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005991 }
5992 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005993 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005994 return ret;
5995 } else {
5996 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005997 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005998 if (out->muted)
5999 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006000 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
6001 __func__, frames, frame_size, bytes_to_write);
6002
Aalique Grahame22e49102018-12-18 14:23:57 -08006003 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07006004 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
6005 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
6006 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006007 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
6008 int16_t *src = (int16_t *)buffer;
6009 int16_t *dst = (int16_t *)buffer;
6010
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006011 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006012 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006013 "out_write called for %s use case with wrong properties",
6014 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006015
6016 /*
6017 * FIXME: this can be removed once audio flinger mixer supports
6018 * mono output
6019 */
6020
6021 /*
6022 * Code below goes over each frame in the buffer and adds both
6023 * L and R samples and then divides by 2 to convert to mono
6024 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006025 if (channel_count == 2) {
6026 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6027 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6028 }
6029 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006030 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006031 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006032
6033 // Note: since out_get_presentation_position() is called alternating with out_write()
6034 // by AudioFlinger, we can check underruns using the prior timestamp read.
6035 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6036 if (out->last_fifo_valid) {
6037 // compute drain to see if there is an underrun.
6038 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
6039 const int64_t frames_by_time =
6040 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
6041 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6042
6043 if (underrun > 0) {
6044 simple_stats_log(&out->fifo_underruns, underrun);
6045
6046 ALOGW("%s: underrun(%lld) "
6047 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6048 __func__,
6049 (long long)out->fifo_underruns.n,
6050 (long long)frames_by_time,
6051 (long long)out->last_fifo_frames_remaining);
6052 }
6053 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6054 }
6055
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306056 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006057
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006058 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006059
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006060 if (out->config.rate)
6061 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6062 out->config.rate;
6063
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006064 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006065 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6066
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006067 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006068 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006069 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306070 out->convert_buffer != NULL) {
6071
6072 memcpy_by_audio_format(out->convert_buffer,
6073 out->hal_op_format,
6074 buffer,
6075 out->hal_ip_format,
6076 out->config.period_size * out->config.channels);
6077
6078 ret = pcm_write(out->pcm, out->convert_buffer,
6079 (out->config.period_size *
6080 out->config.channels *
6081 format_to_bitwidth_table[out->hal_op_format]));
6082 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306083 /*
6084 * To avoid underrun in DSP when the application is not pumping
6085 * data at required rate, check for the no. of bytes and ignore
6086 * pcm_write if it is less than actual buffer size.
6087 * It is a work around to a change in compress VOIP driver.
6088 */
6089 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6090 bytes < (out->config.period_size * out->config.channels *
6091 audio_bytes_per_sample(out->format))) {
6092 size_t voip_buf_size =
6093 out->config.period_size * out->config.channels *
6094 audio_bytes_per_sample(out->format);
6095 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6096 __func__, bytes, voip_buf_size);
6097 usleep(((uint64_t)voip_buf_size - bytes) *
6098 1000000 / audio_stream_out_frame_size(stream) /
6099 out_get_sample_rate(&out->stream.common));
6100 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006101 } else {
6102 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6103 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6104 else
6105 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6106 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306107 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006108
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006109 release_out_focus(out);
6110
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306111 if (ret < 0)
6112 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006113 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306114 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006115 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006116 }
6117
6118exit:
Zhou Songc9672822017-08-16 16:01:39 +08006119 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306120 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306121 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306122 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006123 pthread_mutex_unlock(&out->lock);
6124
6125 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006126 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006127 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306128 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306129 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306130 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306131 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306132 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306133 out->standby = true;
6134 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306135 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006136 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6137 /* prevent division-by-zero */
6138 uint32_t stream_size = audio_stream_out_frame_size(stream);
6139 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006140
Dieter Luecking5d57def2018-09-07 14:23:37 +02006141 if ((stream_size == 0) || (srate == 0)) {
6142 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6143 ATRACE_END();
6144 return -EINVAL;
6145 }
6146 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6147 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006148 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306149 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006150 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006151 return ret;
6152 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006153 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006154 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006155 return bytes;
6156}
6157
6158static int out_get_render_position(const struct audio_stream_out *stream,
6159 uint32_t *dsp_frames)
6160{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006161 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006162
6163 if (dsp_frames == NULL)
6164 return -EINVAL;
6165
6166 *dsp_frames = 0;
6167 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006168 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306169
6170 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6171 * this operation and adev_close_output_stream(where out gets reset).
6172 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306173 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006174 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306175 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006176 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306177 return 0;
6178 }
6179
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006180 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306181 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306182 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006183 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306184 if (ret < 0)
6185 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006186 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306187 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006188 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306189 if (-ENETRESET == ret) {
6190 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306191 out->card_status = CARD_STATUS_OFFLINE;
6192 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306193 } else if(ret < 0) {
6194 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306195 ret = -EINVAL;
6196 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306197 /*
6198 * Handle corner case where compress session is closed during SSR
6199 * and timestamp is queried
6200 */
6201 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306202 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306203 } else if (out->prev_card_status_offline) {
6204 ALOGE("ERROR: previously sound card was offline,return error");
6205 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306206 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306207 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006208 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306209 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306210 pthread_mutex_unlock(&out->lock);
6211 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006212 } else if (audio_is_linear_pcm(out->format)) {
6213 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006214 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006215 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006216 } else
6217 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006218}
6219
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006220static int out_add_audio_effect(const struct audio_stream *stream __unused,
6221 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006222{
6223 return 0;
6224}
6225
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006226static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6227 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006228{
6229 return 0;
6230}
6231
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006232static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6233 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006234{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306235 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006236}
6237
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006238static int out_get_presentation_position(const struct audio_stream_out *stream,
6239 uint64_t *frames, struct timespec *timestamp)
6240{
6241 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306242 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006243 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006244
Ashish Jain5106d362016-05-11 19:23:33 +05306245 /* below piece of code is not guarded against any lock because audioFliner serializes
6246 * this operation and adev_close_output_stream( where out gets reset).
6247 */
6248 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306249 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006250 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306251 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6252 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6253 return 0;
6254 }
6255
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006256 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006257
Ashish Jain5106d362016-05-11 19:23:33 +05306258 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6259 ret = compress_get_tstamp(out->compr, &dsp_frames,
6260 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006261 // Adjustment accounts for A2dp encoder latency with offload usecases
6262 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006263 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006264 unsigned long offset =
6265 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6266 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6267 }
Ashish Jain5106d362016-05-11 19:23:33 +05306268 ALOGVV("%s rendered frames %ld sample_rate %d",
6269 __func__, dsp_frames, out->sample_rate);
6270 *frames = dsp_frames;
6271 if (ret < 0)
6272 ret = -errno;
6273 if (-ENETRESET == ret) {
6274 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306275 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306276 ret = -EINVAL;
6277 } else
6278 ret = 0;
6279 /* this is the best we can do */
6280 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006281 } else {
6282 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006283 unsigned int avail;
6284 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006285 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006286 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006287
Andy Hunga1f48fa2019-07-01 18:14:53 -07006288 if (out->kernel_buffer_size > avail) {
6289 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6290 } else {
6291 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6292 __func__, avail, out->kernel_buffer_size);
6293 avail = out->kernel_buffer_size;
6294 frames_temp = out->last_fifo_frames_remaining = 0;
6295 }
6296 out->last_fifo_valid = true;
6297 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6298
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006299 if (out->written >= frames_temp)
6300 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006301
Andy Hunga1f48fa2019-07-01 18:14:53 -07006302 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6303 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6304
Weiyin Jiangd4633762018-03-16 12:05:03 +08006305 // This adjustment accounts for buffering after app processor.
6306 // It is based on estimated DSP latency per use case, rather than exact.
Robert Lee58215542019-07-15 20:55:12 +08006307 pthread_mutex_lock(&adev->lock);
6308 frames_temp = platform_render_latency(out->dev, out->usecase) *
6309 out->sample_rate / 1000000LL;
6310 pthread_mutex_unlock(&adev->lock);
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006311 if (signed_frames >= frames_temp)
6312 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006313
Weiyin Jiangd4633762018-03-16 12:05:03 +08006314 // Adjustment accounts for A2dp encoder latency with non offload usecases
6315 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006316 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006317 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6318 if (signed_frames >= frames_temp)
6319 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006320 }
6321
6322 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006323 *frames = signed_frames;
6324 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006325 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006326 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6327 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006328 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306329 *frames = out->written;
6330 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306331 if (is_offload_usecase(out->usecase))
6332 ret = -EINVAL;
6333 else
6334 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006335 }
6336 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006337 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006338 return ret;
6339}
6340
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006341static int out_set_callback(struct audio_stream_out *stream,
6342 stream_callback_t callback, void *cookie)
6343{
6344 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006345 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006346
6347 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006348 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006349 out->client_callback = callback;
6350 out->client_cookie = cookie;
6351 if (out->adsp_hdlr_stream_handle) {
6352 ret = audio_extn_adsp_hdlr_stream_set_callback(
6353 out->adsp_hdlr_stream_handle,
6354 callback,
6355 cookie);
6356 if (ret)
6357 ALOGW("%s:adsp hdlr callback registration failed %d",
6358 __func__, ret);
6359 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006360 pthread_mutex_unlock(&out->lock);
6361 return 0;
6362}
6363
6364static int out_pause(struct audio_stream_out* stream)
6365{
6366 struct stream_out *out = (struct stream_out *)stream;
6367 int status = -ENOSYS;
6368 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006369 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006370 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306371 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006372 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006373 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306374 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306375 status = compress_pause(out->compr);
6376
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006377 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006378
Mingming Yin21854652016-04-13 11:54:02 -07006379 if (audio_extn_passthru_is_active()) {
6380 ALOGV("offload use case, pause passthru");
6381 audio_extn_passthru_on_pause(out);
6382 }
6383
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306384 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006385 audio_extn_dts_notify_playback_state(out->usecase, 0,
6386 out->sample_rate, popcount(out->channel_mask),
6387 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006388 }
6389 pthread_mutex_unlock(&out->lock);
6390 }
6391 return status;
6392}
6393
6394static int out_resume(struct audio_stream_out* stream)
6395{
6396 struct stream_out *out = (struct stream_out *)stream;
6397 int status = -ENOSYS;
6398 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006399 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006400 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306401 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006402 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006403 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306404 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306405 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006406 }
6407 if (!status) {
6408 out->offload_state = OFFLOAD_STATE_PLAYING;
6409 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306410 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006411 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6412 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006413 }
6414 pthread_mutex_unlock(&out->lock);
6415 }
6416 return status;
6417}
6418
6419static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6420{
6421 struct stream_out *out = (struct stream_out *)stream;
6422 int status = -ENOSYS;
6423 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006424 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006425 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006426 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6427 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6428 else
6429 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6430 pthread_mutex_unlock(&out->lock);
6431 }
6432 return status;
6433}
6434
6435static int out_flush(struct audio_stream_out* stream)
6436{
6437 struct stream_out *out = (struct stream_out *)stream;
6438 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006439 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006440 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006441 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006442 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6443 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006444 } else {
6445 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6446 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006447 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006448 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006449 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006450 return 0;
6451 }
6452 return -ENOSYS;
6453}
6454
Haynes Mathew George16081042017-05-31 17:16:49 -07006455static int out_stop(const struct audio_stream_out* stream)
6456{
6457 struct stream_out *out = (struct stream_out *)stream;
6458 struct audio_device *adev = out->dev;
6459 int ret = -ENOSYS;
6460
6461 ALOGV("%s", __func__);
6462 pthread_mutex_lock(&adev->lock);
6463 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6464 out->playback_started && out->pcm != NULL) {
6465 pcm_stop(out->pcm);
6466 ret = stop_output_stream(out);
6467 out->playback_started = false;
6468 }
6469 pthread_mutex_unlock(&adev->lock);
6470 return ret;
6471}
6472
6473static int out_start(const struct audio_stream_out* stream)
6474{
6475 struct stream_out *out = (struct stream_out *)stream;
6476 struct audio_device *adev = out->dev;
6477 int ret = -ENOSYS;
6478
6479 ALOGV("%s", __func__);
6480 pthread_mutex_lock(&adev->lock);
6481 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6482 !out->playback_started && out->pcm != NULL) {
6483 ret = start_output_stream(out);
6484 if (ret == 0) {
6485 out->playback_started = true;
6486 }
6487 }
6488 pthread_mutex_unlock(&adev->lock);
6489 return ret;
6490}
6491
6492/*
6493 * Modify config->period_count based on min_size_frames
6494 */
6495static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6496{
6497 int periodCountRequested = (min_size_frames + config->period_size - 1)
6498 / config->period_size;
6499 int periodCount = MMAP_PERIOD_COUNT_MIN;
6500
6501 ALOGV("%s original config.period_size = %d config.period_count = %d",
6502 __func__, config->period_size, config->period_count);
6503
6504 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6505 periodCount *= 2;
6506 }
6507 config->period_count = periodCount;
6508
6509 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6510}
6511
Phil Burkfe17efd2019-03-25 10:23:35 -07006512// Read offset for the positional timestamp from a persistent vendor property.
6513// This is to workaround apparent inaccuracies in the timing information that
6514// is used by the AAudio timing model. The inaccuracies can cause glitches.
6515static int64_t get_mmap_out_time_offset() {
6516 const int32_t kDefaultOffsetMicros = 0;
6517 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006518 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006519 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6520 return mmap_time_offset_micros * (int64_t)1000;
6521}
6522
Haynes Mathew George16081042017-05-31 17:16:49 -07006523static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6524 int32_t min_size_frames,
6525 struct audio_mmap_buffer_info *info)
6526{
6527 struct stream_out *out = (struct stream_out *)stream;
6528 struct audio_device *adev = out->dev;
6529 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006530 unsigned int offset1 = 0;
6531 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006532 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006533 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006534 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006535
Arun Mirpuri5d170872019-03-26 13:21:31 -07006536 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306537 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006538 pthread_mutex_lock(&adev->lock);
6539
Sharad Sanglec6f32552018-05-04 16:15:38 +05306540 if (CARD_STATUS_OFFLINE == out->card_status ||
6541 CARD_STATUS_OFFLINE == adev->card_status) {
6542 ALOGW("out->card_status or adev->card_status offline, try again");
6543 ret = -EIO;
6544 goto exit;
6545 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306546 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006547 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6548 ret = -EINVAL;
6549 goto exit;
6550 }
6551 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6552 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6553 ret = -ENOSYS;
6554 goto exit;
6555 }
6556 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6557 if (out->pcm_device_id < 0) {
6558 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6559 __func__, out->pcm_device_id, out->usecase);
6560 ret = -EINVAL;
6561 goto exit;
6562 }
6563
6564 adjust_mmap_period_count(&out->config, min_size_frames);
6565
Arun Mirpuri5d170872019-03-26 13:21:31 -07006566 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006567 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6568 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6569 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306570 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306571 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6572 out->card_status = CARD_STATUS_OFFLINE;
6573 adev->card_status = CARD_STATUS_OFFLINE;
6574 ret = -EIO;
6575 goto exit;
6576 }
6577
Haynes Mathew George16081042017-05-31 17:16:49 -07006578 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6579 step = "open";
6580 ret = -ENODEV;
6581 goto exit;
6582 }
6583 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6584 if (ret < 0) {
6585 step = "begin";
6586 goto exit;
6587 }
juyuchen626833d2019-06-04 16:48:02 +08006588
6589 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006590 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006591 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006592 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006593 ret = platform_get_mmap_data_fd(adev->platform,
6594 out->pcm_device_id, 0 /*playback*/,
6595 &info->shared_memory_fd,
6596 &mmap_size);
6597 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006598 // Fall back to non exclusive mode
6599 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6600 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006601 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6602 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6603
Arun Mirpuri5d170872019-03-26 13:21:31 -07006604 if (mmap_size < buffer_size) {
6605 step = "mmap";
6606 goto exit;
6607 }
juyuchen626833d2019-06-04 16:48:02 +08006608 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006609 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006610 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006611 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006612
6613 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6614 if (ret < 0) {
6615 step = "commit";
6616 goto exit;
6617 }
6618
Phil Burkfe17efd2019-03-25 10:23:35 -07006619 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6620
Haynes Mathew George16081042017-05-31 17:16:49 -07006621 out->standby = false;
6622 ret = 0;
6623
Arun Mirpuri5d170872019-03-26 13:21:31 -07006624 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006625 __func__, info->shared_memory_address, info->buffer_size_frames);
6626
6627exit:
6628 if (ret != 0) {
6629 if (out->pcm == NULL) {
6630 ALOGE("%s: %s - %d", __func__, step, ret);
6631 } else {
6632 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6633 pcm_close(out->pcm);
6634 out->pcm = NULL;
6635 }
6636 }
6637 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306638 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006639 return ret;
6640}
6641
6642static int out_get_mmap_position(const struct audio_stream_out *stream,
6643 struct audio_mmap_position *position)
6644{
6645 struct stream_out *out = (struct stream_out *)stream;
6646 ALOGVV("%s", __func__);
6647 if (position == NULL) {
6648 return -EINVAL;
6649 }
6650 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006651 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006652 return -ENOSYS;
6653 }
6654 if (out->pcm == NULL) {
6655 return -ENOSYS;
6656 }
6657
6658 struct timespec ts = { 0, 0 };
6659 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6660 if (ret < 0) {
6661 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6662 return ret;
6663 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006664 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6665 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006666 return 0;
6667}
6668
6669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006670/** audio_stream_in implementation **/
6671static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6672{
6673 struct stream_in *in = (struct stream_in *)stream;
6674
6675 return in->config.rate;
6676}
6677
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006678static int in_set_sample_rate(struct audio_stream *stream __unused,
6679 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006680{
6681 return -ENOSYS;
6682}
6683
6684static size_t in_get_buffer_size(const struct audio_stream *stream)
6685{
6686 struct stream_in *in = (struct stream_in *)stream;
6687
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006688 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6689 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006690 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6691 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306692 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306693 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006694
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006695 return in->config.period_size * in->af_period_multiplier *
6696 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006697}
6698
6699static uint32_t in_get_channels(const struct audio_stream *stream)
6700{
6701 struct stream_in *in = (struct stream_in *)stream;
6702
6703 return in->channel_mask;
6704}
6705
6706static audio_format_t in_get_format(const struct audio_stream *stream)
6707{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006708 struct stream_in *in = (struct stream_in *)stream;
6709
6710 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006711}
6712
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006713static int in_set_format(struct audio_stream *stream __unused,
6714 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006715{
6716 return -ENOSYS;
6717}
6718
6719static int in_standby(struct audio_stream *stream)
6720{
6721 struct stream_in *in = (struct stream_in *)stream;
6722 struct audio_device *adev = in->dev;
6723 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306724 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6725 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006726 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306727
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006728 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006729 if (!in->standby && in->is_st_session) {
6730 ALOGD("%s: sound trigger pcm stop lab", __func__);
6731 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006732 if (adev->num_va_sessions > 0)
6733 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006734 in->standby = 1;
6735 }
6736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006737 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006738 if (adev->adm_deregister_stream)
6739 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6740
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006741 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006742 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006743 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006744 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006745 voice_extn_compress_voip_close_input_stream(stream);
6746 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006747 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6748 do_stop = in->capture_started;
6749 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006750 if (in->mmap_shared_memory_fd >= 0) {
6751 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6752 __func__, in->mmap_shared_memory_fd);
6753 close(in->mmap_shared_memory_fd);
6754 in->mmap_shared_memory_fd = -1;
6755 }
Zhou Songa8895042016-07-05 17:54:22 +08006756 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306757 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306758 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006759 }
6760
Arun Mirpuri5d170872019-03-26 13:21:31 -07006761 if (in->pcm) {
6762 ATRACE_BEGIN("pcm_in_close");
6763 pcm_close(in->pcm);
6764 ATRACE_END();
6765 in->pcm = NULL;
6766 }
6767
Carter Hsu2e429db2019-05-14 18:50:52 +08006768 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006769 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006770
George Gao3018ede2019-10-23 13:23:00 -07006771 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6772 if (adev->num_va_sessions > 0)
6773 adev->num_va_sessions--;
6774 }
Quinn Malef6050362019-01-30 15:55:40 -08006775
Eric Laurent150dbfe2013-02-27 14:31:02 -08006776 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006777 }
6778 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006779 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006780 return status;
6781}
6782
Aalique Grahame22e49102018-12-18 14:23:57 -08006783static int in_dump(const struct audio_stream *stream,
6784 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006785{
Aalique Grahame22e49102018-12-18 14:23:57 -08006786 struct stream_in *in = (struct stream_in *)stream;
6787
6788 // We try to get the lock for consistency,
6789 // but it isn't necessary for these variables.
6790 // If we're not in standby, we may be blocked on a read.
6791 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6792 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6793 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6794 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6795
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006796 char buffer[256]; // for statistics formatting
6797 if (in->start_latency_ms.n > 0) {
6798 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6799 dprintf(fd, " Start latency ms: %s\n", buffer);
6800 }
6801
Aalique Grahame22e49102018-12-18 14:23:57 -08006802 if (locked) {
6803 pthread_mutex_unlock(&in->lock);
6804 }
6805
6806 // dump error info
6807 (void)error_log_dump(
6808 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006810 return 0;
6811}
6812
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306813static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6814{
6815 if (!stream || !parms)
6816 return;
6817
6818 struct stream_in *in = (struct stream_in *)stream;
6819 struct audio_device *adev = in->dev;
6820
6821 card_status_t status;
6822 int card;
6823 if (parse_snd_card_status(parms, &card, &status) < 0)
6824 return;
6825
6826 pthread_mutex_lock(&adev->lock);
6827 bool valid_cb = (card == adev->snd_card);
6828 pthread_mutex_unlock(&adev->lock);
6829
6830 if (!valid_cb)
6831 return;
6832
6833 lock_input_stream(in);
6834 if (in->card_status != status)
6835 in->card_status = status;
6836 pthread_mutex_unlock(&in->lock);
6837
6838 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6839 use_case_table[in->usecase],
6840 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6841
6842 // a better solution would be to report error back to AF and let
6843 // it put the stream to standby
6844 if (status == CARD_STATUS_OFFLINE)
6845 in_standby(&in->stream.common);
6846
6847 return;
6848}
6849
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006850int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006851 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006852 audio_source_t source)
6853{
6854 struct audio_device *adev = in->dev;
6855 int ret = 0;
6856
6857 lock_input_stream(in);
6858 pthread_mutex_lock(&adev->lock);
6859
6860 /* no audio source uses val == 0 */
6861 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6862 in->source = source;
6863 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6864 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6865 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6866 (in->config.rate == 8000 || in->config.rate == 16000 ||
6867 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6868 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6869 ret = voice_extn_compress_voip_open_input_stream(in);
6870 if (ret != 0) {
6871 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6872 __func__, ret);
6873 }
6874 }
6875 }
6876
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006877 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6878 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006879 // Workaround: If routing to an non existing usb device, fail gracefully
6880 // The routing request will otherwise block during 10 second
6881 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006882 struct str_parms *usb_addr =
6883 str_parms_create_str(get_usb_device_address(devices));
6884 if (is_usb_in_device_type(devices) && usb_addr &&
6885 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006886 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6887 ret = -ENOSYS;
6888 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006889 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006890 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006891 if (!in->standby && !in->is_st_session) {
6892 ALOGV("update input routing change");
6893 // inform adm before actual routing to prevent glitches.
6894 if (adev->adm_on_routing_change) {
6895 adev->adm_on_routing_change(adev->adm_data,
6896 in->capture_handle);
6897 ret = select_devices(adev, in->usecase);
6898 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6899 adev->adm_routing_changed = true;
6900 }
6901 }
6902 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006903 if (usb_addr)
6904 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006905 }
6906 pthread_mutex_unlock(&adev->lock);
6907 pthread_mutex_unlock(&in->lock);
6908
6909 ALOGD("%s: exit: status(%d)", __func__, ret);
6910 return ret;
6911}
6912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006913static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6914{
6915 struct stream_in *in = (struct stream_in *)stream;
6916 struct audio_device *adev = in->dev;
6917 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006918 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306919 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006920
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306921 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006922 parms = str_parms_create_str(kvpairs);
6923
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306924 if (!parms)
6925 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006926 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006927 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006928
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306929 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6930 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306931 strlcpy(in->profile, value, sizeof(in->profile));
6932 ALOGV("updating stream profile with value '%s'", in->profile);
6933 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6934 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006935 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306936 in->sample_rate, in->bit_width,
6937 in->profile, &in->app_type_cfg);
6938 }
6939
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006940 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006941 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006942
6943 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306944error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306945 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006946}
6947
6948static char* in_get_parameters(const struct audio_stream *stream,
6949 const char *keys)
6950{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006951 struct stream_in *in = (struct stream_in *)stream;
6952 struct str_parms *query = str_parms_create_str(keys);
6953 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006954 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006955
6956 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006957 if (reply) {
6958 str_parms_destroy(reply);
6959 }
6960 if (query) {
6961 str_parms_destroy(query);
6962 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006963 ALOGE("in_get_parameters: failed to create query or reply");
6964 return NULL;
6965 }
6966
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006967 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006968
6969 voice_extn_in_get_parameters(in, query, reply);
6970
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006971 stream_get_parameter_channels(query, reply,
6972 &in->supported_channel_masks[0]);
6973 stream_get_parameter_formats(query, reply,
6974 &in->supported_formats[0]);
6975 stream_get_parameter_rates(query, reply,
6976 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006977 str = str_parms_to_str(reply);
6978 str_parms_destroy(query);
6979 str_parms_destroy(reply);
6980
6981 ALOGV("%s: exit: returns - %s", __func__, str);
6982 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006983}
6984
Aalique Grahame22e49102018-12-18 14:23:57 -08006985static int in_set_gain(struct audio_stream_in *stream,
6986 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006987{
Aalique Grahame22e49102018-12-18 14:23:57 -08006988 struct stream_in *in = (struct stream_in *)stream;
6989 char mixer_ctl_name[128];
6990 struct mixer_ctl *ctl;
6991 int ctl_value;
6992
6993 ALOGV("%s: gain %f", __func__, gain);
6994
6995 if (stream == NULL)
6996 return -EINVAL;
6997
6998 /* in_set_gain() only used to silence MMAP capture for now */
6999 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
7000 return -ENOSYS;
7001
7002 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
7003
7004 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
7005 if (!ctl) {
7006 ALOGW("%s: Could not get ctl for mixer cmd - %s",
7007 __func__, mixer_ctl_name);
7008 return -ENOSYS;
7009 }
7010
7011 if (gain < RECORD_GAIN_MIN)
7012 gain = RECORD_GAIN_MIN;
7013 else if (gain > RECORD_GAIN_MAX)
7014 gain = RECORD_GAIN_MAX;
7015 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7016
7017 mixer_ctl_set_value(ctl, 0, ctl_value);
7018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007019 return 0;
7020}
7021
7022static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7023 size_t bytes)
7024{
7025 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307026
7027 if (in == NULL) {
7028 ALOGE("%s: stream_in ptr is NULL", __func__);
7029 return -EINVAL;
7030 }
7031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007032 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307033 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307034 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007035
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007036 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307037
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007038 if (in->is_st_session) {
7039 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7040 /* Read from sound trigger HAL */
7041 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007042 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007043 if (adev->num_va_sessions < UINT_MAX)
7044 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007045 in->standby = 0;
7046 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007047 pthread_mutex_unlock(&in->lock);
7048 return bytes;
7049 }
7050
Haynes Mathew George16081042017-05-31 17:16:49 -07007051 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7052 ret = -ENOSYS;
7053 goto exit;
7054 }
7055
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007056 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7057 !in->standby && adev->adm_routing_changed) {
7058 ret = -ENOSYS;
7059 goto exit;
7060 }
7061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007062 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007063 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7064
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007065 pthread_mutex_lock(&adev->lock);
7066 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7067 ret = voice_extn_compress_voip_start_input_stream(in);
7068 else
7069 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007070 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7071 if (adev->num_va_sessions < UINT_MAX)
7072 adev->num_va_sessions++;
7073 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007074 pthread_mutex_unlock(&adev->lock);
7075 if (ret != 0) {
7076 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007077 }
7078 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007079
7080 // log startup time in ms.
7081 simple_stats_log(
7082 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007083 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007084
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307085 /* Avoid read if capture_stopped is set */
7086 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7087 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7088 ret = -EINVAL;
7089 goto exit;
7090 }
7091
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007092 // what's the duration requested by the client?
7093 long ns = 0;
7094
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307095 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007096 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7097 in->config.rate;
7098
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007099 ret = request_in_focus(in, ns);
7100 if (ret != 0)
7101 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007102 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007103
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307104 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307105 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7106 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307107 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007108 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307109 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007110 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007111 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007112 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007113 } else if (audio_extn_ffv_get_stream() == in) {
7114 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307115 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007116 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307117 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7118 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7119 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7120 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307121 ret = -EINVAL;
7122 goto exit;
7123 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307124 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307125 ret = -errno;
7126 }
7127 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307128 /* bytes read is always set to bytes for non compress usecases */
7129 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007130 }
7131
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007132 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007134 /*
Quinn Malef6050362019-01-30 15:55:40 -08007135 * Instead of writing zeroes here, we could trust the hardware to always
7136 * provide zeroes when muted. This is also muted with voice recognition
7137 * usecases so that other clients do not have access to voice recognition
7138 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007139 */
Quinn Malef6050362019-01-30 15:55:40 -08007140 if ((ret == 0 && voice_get_mic_mute(adev) &&
7141 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007142 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7143 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007144 (adev->num_va_sessions &&
7145 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7146 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7147 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007148 memset(buffer, 0, bytes);
7149
7150exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307151 frame_size = audio_stream_in_frame_size(stream);
7152 if (frame_size > 0)
7153 in->frames_read += bytes_read/frame_size;
7154
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007155 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307156 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007157 pthread_mutex_unlock(&in->lock);
7158
7159 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307160 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307161 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307162 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307163 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307164 in->standby = true;
7165 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307166 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307167 bytes_read = bytes;
7168 memset(buffer, 0, bytes);
7169 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007170 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007171 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7172 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007173 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307174 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307175 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007176 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307177 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007178}
7179
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007180static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007181{
7182 return 0;
7183}
7184
Aalique Grahame22e49102018-12-18 14:23:57 -08007185static int in_get_capture_position(const struct audio_stream_in *stream,
7186 int64_t *frames, int64_t *time)
7187{
7188 if (stream == NULL || frames == NULL || time == NULL) {
7189 return -EINVAL;
7190 }
7191 struct stream_in *in = (struct stream_in *)stream;
7192 int ret = -ENOSYS;
7193
7194 lock_input_stream(in);
7195 // note: ST sessions do not close the alsa pcm driver synchronously
7196 // on standby. Therefore, we may return an error even though the
7197 // pcm stream is still opened.
7198 if (in->standby) {
7199 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7200 "%s stream in standby but pcm not NULL for non ST session", __func__);
7201 goto exit;
7202 }
7203 if (in->pcm) {
7204 struct timespec timestamp;
7205 unsigned int avail;
7206 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7207 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007208 pthread_mutex_lock(&adev->lock);
7209 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
7210 - platform_capture_latency(in->dev, in->usecase) * 1000LL;
7211 pthread_mutex_unlock(&adev->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08007212 ret = 0;
7213 }
7214 }
7215exit:
7216 pthread_mutex_unlock(&in->lock);
7217 return ret;
7218}
7219
Carter Hsu2e429db2019-05-14 18:50:52 +08007220static int in_update_effect_list(bool add, effect_handle_t effect,
7221 struct listnode *head)
7222{
7223 struct listnode *node;
7224 struct in_effect_list *elist = NULL;
7225 struct in_effect_list *target = NULL;
7226 int ret = 0;
7227
7228 if (!head)
7229 return ret;
7230
7231 list_for_each(node, head) {
7232 elist = node_to_item(node, struct in_effect_list, list);
7233 if (elist->handle == effect) {
7234 target = elist;
7235 break;
7236 }
7237 }
7238
7239 if (add) {
7240 if (target) {
7241 ALOGD("effect %p already exist", effect);
7242 return ret;
7243 }
7244
7245 target = (struct in_effect_list *)
7246 calloc(1, sizeof(struct in_effect_list));
7247
7248 if (!target) {
7249 ALOGE("%s:fail to allocate memory", __func__);
7250 return -ENOMEM;
7251 }
7252
7253 target->handle = effect;
7254 list_add_tail(head, &target->list);
7255 } else {
7256 if (target) {
7257 list_remove(&target->list);
7258 free(target);
7259 }
7260 }
7261
7262 return ret;
7263}
7264
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007265static int add_remove_audio_effect(const struct audio_stream *stream,
7266 effect_handle_t effect,
7267 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007268{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007269 struct stream_in *in = (struct stream_in *)stream;
7270 int status = 0;
7271 effect_descriptor_t desc;
7272
7273 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007274 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7275
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007276 if (status != 0)
7277 return status;
7278
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007279 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007280 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007281 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007282 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7283 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007284 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007285
7286 in_update_effect_list(enable, effect, &in->aec_list);
7287 enable = !list_empty(&in->aec_list);
7288 if (enable == in->enable_aec)
7289 goto exit;
7290
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007291 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007292 ALOGD("AEC enable %d", enable);
7293
Aalique Grahame22e49102018-12-18 14:23:57 -08007294 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7295 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7296 in->dev->enable_voicerx = enable;
7297 struct audio_usecase *usecase;
7298 struct listnode *node;
7299 list_for_each(node, &in->dev->usecase_list) {
7300 usecase = node_to_item(node, struct audio_usecase, list);
7301 if (usecase->type == PCM_PLAYBACK)
7302 select_devices(in->dev, usecase->id);
7303 }
7304 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007305 if (!in->standby) {
7306 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7307 select_devices(in->dev, in->usecase);
7308 }
7309
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007310 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007311 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7312
7313 in_update_effect_list(enable, effect, &in->ns_list);
7314 enable = !list_empty(&in->ns_list);
7315 if (enable == in->enable_ns)
7316 goto exit;
7317
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007318 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007319 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007320 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007321 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7322 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007323 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7324 select_devices(in->dev, in->usecase);
7325 } else
7326 select_devices(in->dev, in->usecase);
7327 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007328 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007329exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007330 pthread_mutex_unlock(&in->dev->lock);
7331 pthread_mutex_unlock(&in->lock);
7332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007333 return 0;
7334}
7335
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007336static int in_add_audio_effect(const struct audio_stream *stream,
7337 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007338{
Eric Laurent994a6932013-07-17 11:51:42 -07007339 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007340 return add_remove_audio_effect(stream, effect, true);
7341}
7342
7343static int in_remove_audio_effect(const struct audio_stream *stream,
7344 effect_handle_t effect)
7345{
Eric Laurent994a6932013-07-17 11:51:42 -07007346 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007347 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007348}
7349
Derek Chenf939fb72018-11-13 13:34:41 -08007350streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7351 audio_io_handle_t input)
7352{
7353 struct listnode *node;
7354
7355 list_for_each(node, &dev->active_inputs_list) {
7356 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7357 streams_input_ctxt_t,
7358 list);
7359 if (in_ctxt->input->capture_handle == input) {
7360 return in_ctxt;
7361 }
7362 }
7363 return NULL;
7364}
7365
7366streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7367 audio_io_handle_t output)
7368{
7369 struct listnode *node;
7370
7371 list_for_each(node, &dev->active_outputs_list) {
7372 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7373 streams_output_ctxt_t,
7374 list);
7375 if (out_ctxt->output->handle == output) {
7376 return out_ctxt;
7377 }
7378 }
7379 return NULL;
7380}
7381
Haynes Mathew George16081042017-05-31 17:16:49 -07007382static int in_stop(const struct audio_stream_in* stream)
7383{
7384 struct stream_in *in = (struct stream_in *)stream;
7385 struct audio_device *adev = in->dev;
7386
7387 int ret = -ENOSYS;
7388 ALOGV("%s", __func__);
7389 pthread_mutex_lock(&adev->lock);
7390 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7391 in->capture_started && in->pcm != NULL) {
7392 pcm_stop(in->pcm);
7393 ret = stop_input_stream(in);
7394 in->capture_started = false;
7395 }
7396 pthread_mutex_unlock(&adev->lock);
7397 return ret;
7398}
7399
7400static int in_start(const struct audio_stream_in* stream)
7401{
7402 struct stream_in *in = (struct stream_in *)stream;
7403 struct audio_device *adev = in->dev;
7404 int ret = -ENOSYS;
7405
7406 ALOGV("%s in %p", __func__, in);
7407 pthread_mutex_lock(&adev->lock);
7408 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7409 !in->capture_started && in->pcm != NULL) {
7410 if (!in->capture_started) {
7411 ret = start_input_stream(in);
7412 if (ret == 0) {
7413 in->capture_started = true;
7414 }
7415 }
7416 }
7417 pthread_mutex_unlock(&adev->lock);
7418 return ret;
7419}
7420
Phil Burke0a86d12019-02-16 22:28:11 -08007421// Read offset for the positional timestamp from a persistent vendor property.
7422// This is to workaround apparent inaccuracies in the timing information that
7423// is used by the AAudio timing model. The inaccuracies can cause glitches.
7424static int64_t in_get_mmap_time_offset() {
7425 const int32_t kDefaultOffsetMicros = 0;
7426 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007427 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007428 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7429 return mmap_time_offset_micros * (int64_t)1000;
7430}
7431
Haynes Mathew George16081042017-05-31 17:16:49 -07007432static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7433 int32_t min_size_frames,
7434 struct audio_mmap_buffer_info *info)
7435{
7436 struct stream_in *in = (struct stream_in *)stream;
7437 struct audio_device *adev = in->dev;
7438 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007439 unsigned int offset1 = 0;
7440 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007441 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007442 uint32_t mmap_size = 0;
7443 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007444
7445 pthread_mutex_lock(&adev->lock);
7446 ALOGV("%s in %p", __func__, in);
7447
Sharad Sanglec6f32552018-05-04 16:15:38 +05307448 if (CARD_STATUS_OFFLINE == in->card_status||
7449 CARD_STATUS_OFFLINE == adev->card_status) {
7450 ALOGW("in->card_status or adev->card_status offline, try again");
7451 ret = -EIO;
7452 goto exit;
7453 }
7454
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307455 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007456 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7457 ret = -EINVAL;
7458 goto exit;
7459 }
7460 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7461 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7462 ALOGV("%s in %p", __func__, in);
7463 ret = -ENOSYS;
7464 goto exit;
7465 }
7466 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7467 if (in->pcm_device_id < 0) {
7468 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7469 __func__, in->pcm_device_id, in->usecase);
7470 ret = -EINVAL;
7471 goto exit;
7472 }
7473
7474 adjust_mmap_period_count(&in->config, min_size_frames);
7475
7476 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7477 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7478 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7479 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307480 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307481 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7482 in->card_status = CARD_STATUS_OFFLINE;
7483 adev->card_status = CARD_STATUS_OFFLINE;
7484 ret = -EIO;
7485 goto exit;
7486 }
7487
Haynes Mathew George16081042017-05-31 17:16:49 -07007488 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7489 step = "open";
7490 ret = -ENODEV;
7491 goto exit;
7492 }
7493
7494 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7495 if (ret < 0) {
7496 step = "begin";
7497 goto exit;
7498 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007499
juyuchen626833d2019-06-04 16:48:02 +08007500 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007501 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7502 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7503 info->burst_size_frames = in->config.period_size;
7504 ret = platform_get_mmap_data_fd(adev->platform,
7505 in->pcm_device_id, 1 /*capture*/,
7506 &info->shared_memory_fd,
7507 &mmap_size);
7508 if (ret < 0) {
7509 // Fall back to non exclusive mode
7510 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7511 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007512 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7513 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7514
Arun Mirpuri5d170872019-03-26 13:21:31 -07007515 if (mmap_size < buffer_size) {
7516 step = "mmap";
7517 goto exit;
7518 }
juyuchen626833d2019-06-04 16:48:02 +08007519 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007520 }
7521
7522 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007523
7524 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7525 if (ret < 0) {
7526 step = "commit";
7527 goto exit;
7528 }
7529
Phil Burke0a86d12019-02-16 22:28:11 -08007530 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7531
Haynes Mathew George16081042017-05-31 17:16:49 -07007532 in->standby = false;
7533 ret = 0;
7534
7535 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7536 __func__, info->shared_memory_address, info->buffer_size_frames);
7537
7538exit:
7539 if (ret != 0) {
7540 if (in->pcm == NULL) {
7541 ALOGE("%s: %s - %d", __func__, step, ret);
7542 } else {
7543 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7544 pcm_close(in->pcm);
7545 in->pcm = NULL;
7546 }
7547 }
7548 pthread_mutex_unlock(&adev->lock);
7549 return ret;
7550}
7551
7552static int in_get_mmap_position(const struct audio_stream_in *stream,
7553 struct audio_mmap_position *position)
7554{
7555 struct stream_in *in = (struct stream_in *)stream;
7556 ALOGVV("%s", __func__);
7557 if (position == NULL) {
7558 return -EINVAL;
7559 }
7560 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7561 return -ENOSYS;
7562 }
7563 if (in->pcm == NULL) {
7564 return -ENOSYS;
7565 }
7566 struct timespec ts = { 0, 0 };
7567 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7568 if (ret < 0) {
7569 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7570 return ret;
7571 }
Phil Burke0a86d12019-02-16 22:28:11 -08007572 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7573 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007574 return 0;
7575}
7576
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307577static int in_get_active_microphones(const struct audio_stream_in *stream,
7578 struct audio_microphone_characteristic_t *mic_array,
7579 size_t *mic_count) {
7580 struct stream_in *in = (struct stream_in *)stream;
7581 struct audio_device *adev = in->dev;
7582 ALOGVV("%s", __func__);
7583
7584 lock_input_stream(in);
7585 pthread_mutex_lock(&adev->lock);
7586 int ret = platform_get_active_microphones(adev->platform,
7587 audio_channel_count_from_in_mask(in->channel_mask),
7588 in->usecase, mic_array, mic_count);
7589 pthread_mutex_unlock(&adev->lock);
7590 pthread_mutex_unlock(&in->lock);
7591
7592 return ret;
7593}
7594
7595static int adev_get_microphones(const struct audio_hw_device *dev,
7596 struct audio_microphone_characteristic_t *mic_array,
7597 size_t *mic_count) {
7598 struct audio_device *adev = (struct audio_device *)dev;
7599 ALOGVV("%s", __func__);
7600
7601 pthread_mutex_lock(&adev->lock);
7602 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7603 pthread_mutex_unlock(&adev->lock);
7604
7605 return ret;
7606}
juyuchendb308c22019-01-21 11:57:17 -07007607
7608static void in_update_sink_metadata(struct audio_stream_in *stream,
7609 const struct sink_metadata *sink_metadata) {
7610
7611 if (stream == NULL
7612 || sink_metadata == NULL
7613 || sink_metadata->tracks == NULL) {
7614 return;
7615 }
7616
7617 int error = 0;
7618 struct stream_in *in = (struct stream_in *)stream;
7619 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007620 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007621 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007622
7623 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007624
7625 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007626 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007627
7628 lock_input_stream(in);
7629 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007630 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007631
Zhou Song62ea0282020-03-22 19:53:01 +08007632 is_ha_usecase = adev->ha_proxy_enable ?
7633 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7634 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7635 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007636 && adev->voice_tx_output != NULL) {
7637 /* Use the rx device from afe-proxy record to route voice call because
7638 there is no routing if tx device is on primary hal and rx device
7639 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007640 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007641
7642 if (!voice_is_call_state_active(adev)) {
7643 if (adev->mode == AUDIO_MODE_IN_CALL) {
7644 adev->current_call_output = adev->voice_tx_output;
7645 error = voice_start_call(adev);
7646 if (error != 0)
7647 ALOGE("%s: start voice call failed %d", __func__, error);
7648 }
7649 } else {
7650 adev->current_call_output = adev->voice_tx_output;
7651 voice_update_devices_for_all_voice_usecases(adev);
7652 }
7653 }
7654
7655 pthread_mutex_unlock(&adev->lock);
7656 pthread_mutex_unlock(&in->lock);
7657}
7658
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307659int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007660 audio_io_handle_t handle,
7661 audio_devices_t devices,
7662 audio_output_flags_t flags,
7663 struct audio_config *config,
7664 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007665 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007666{
7667 struct audio_device *adev = (struct audio_device *)dev;
7668 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307669 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007670 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007671 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307672 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007673 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7674 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7675 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7676 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007677 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007678 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7679 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007680 bool force_haptic_path =
7681 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007682 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007683
kunleizdff872d2018-08-20 14:40:33 +08007684 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007685 is_usb_dev = false;
7686 devices = AUDIO_DEVICE_OUT_SPEAKER;
7687 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7688 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007689 if (config->format == AUDIO_FORMAT_DEFAULT)
7690 config->format = AUDIO_FORMAT_PCM_16_BIT;
7691 if (config->sample_rate == 0)
7692 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7693 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7694 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007695 }
7696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007697 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307698
Rahul Sharma99770982019-03-06 17:05:26 +05307699 pthread_mutex_lock(&adev->lock);
7700 if (out_get_stream(adev, handle) != NULL) {
7701 ALOGW("%s, output stream already opened", __func__);
7702 ret = -EEXIST;
7703 }
7704 pthread_mutex_unlock(&adev->lock);
7705 if (ret)
7706 return ret;
7707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007708 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7709
Mingming Yin3a941d42016-02-17 18:08:05 -08007710 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007711 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7712 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307713
7714
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007715 if (!out) {
7716 return -ENOMEM;
7717 }
7718
Haynes Mathew George204045b2015-02-25 20:32:03 -08007719 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007720 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307721 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007722 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007723 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007725 if (devices == AUDIO_DEVICE_NONE)
7726 devices = AUDIO_DEVICE_OUT_SPEAKER;
7727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007728 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007729 list_init(&out->device_list);
7730 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007731 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007732 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007733 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307734 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307735 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7736 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7737 else
7738 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007739 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007740 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007741 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307742 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307743 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307744 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007745 out->hal_output_suspend_supported = 0;
7746 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307747 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307748 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307749 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007750 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007751
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307752 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307753 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007754 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7755
Aalique Grahame22e49102018-12-18 14:23:57 -08007756 if (direct_dev &&
7757 (audio_is_linear_pcm(out->format) ||
7758 config->format == AUDIO_FORMAT_DEFAULT) &&
7759 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7760 audio_format_t req_format = config->format;
7761 audio_channel_mask_t req_channel_mask = config->channel_mask;
7762 uint32_t req_sample_rate = config->sample_rate;
7763
7764 pthread_mutex_lock(&adev->lock);
7765 if (is_hdmi) {
7766 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7767 ret = read_hdmi_sink_caps(out);
7768 if (config->sample_rate == 0)
7769 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7770 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7771 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7772 if (config->format == AUDIO_FORMAT_DEFAULT)
7773 config->format = AUDIO_FORMAT_PCM_16_BIT;
7774 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007775 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7776 &config->format,
7777 &out->supported_formats[0],
7778 MAX_SUPPORTED_FORMATS,
7779 &config->channel_mask,
7780 &out->supported_channel_masks[0],
7781 MAX_SUPPORTED_CHANNEL_MASKS,
7782 &config->sample_rate,
7783 &out->supported_sample_rates[0],
7784 MAX_SUPPORTED_SAMPLE_RATES);
7785 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007786 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007787
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007788 pthread_mutex_unlock(&adev->lock);
7789 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007790 if (ret == -ENOSYS) {
7791 /* ignore and go with default */
7792 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007793 }
7794 // For MMAP NO IRQ, allow conversions in ADSP
7795 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7796 goto error_open;
7797 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007798 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007799 goto error_open;
7800 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007801
7802 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7803 config->sample_rate = req_sample_rate;
7804 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7805 config->channel_mask = req_channel_mask;
7806 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7807 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007808 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007809
7810 out->sample_rate = config->sample_rate;
7811 out->channel_mask = config->channel_mask;
7812 out->format = config->format;
7813 if (is_hdmi) {
7814 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7815 out->config = pcm_config_hdmi_multi;
7816 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7817 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7818 out->config = pcm_config_mmap_playback;
7819 out->stream.start = out_start;
7820 out->stream.stop = out_stop;
7821 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7822 out->stream.get_mmap_position = out_get_mmap_position;
7823 } else {
7824 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7825 out->config = pcm_config_hifi;
7826 }
7827
7828 out->config.rate = out->sample_rate;
7829 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7830 if (is_hdmi) {
7831 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7832 audio_bytes_per_sample(out->format));
7833 }
7834 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007835 }
7836
Derek Chenf6318be2017-06-12 17:16:24 -04007837 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007838 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007839 /* extract car audio stream index */
7840 out->car_audio_stream =
7841 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7842 if (out->car_audio_stream < 0) {
7843 ALOGE("%s: invalid car audio stream %x",
7844 __func__, out->car_audio_stream);
7845 ret = -EINVAL;
7846 goto error_open;
7847 }
Derek Chen5f67a942020-02-24 23:08:13 -08007848 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007849 }
7850
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007851 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007852 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007853 if (!voice_extn_is_compress_voip_supported()) {
7854 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7855 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007856 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307857 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007858 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7859 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007860 out->volume_l = INVALID_OUT_VOLUME;
7861 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007862
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007863 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007864 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007865 uint32_t channel_count =
7866 audio_channel_count_from_out_mask(out->channel_mask);
7867 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7868 out->sample_rate, out->format,
7869 channel_count, false);
7870 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7871 if (frame_size != 0)
7872 out->config.period_size = buffer_size / frame_size;
7873 else
7874 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007875 }
7876 } else {
7877 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7878 voice_extn_compress_voip_is_active(out->dev)) &&
7879 (voice_extn_compress_voip_is_config_supported(config))) {
7880 ret = voice_extn_compress_voip_open_output_stream(out);
7881 if (ret != 0) {
7882 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7883 __func__, ret);
7884 goto error_open;
7885 }
Sujin Panicker19027262019-09-16 18:28:06 +05307886 } else {
7887 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7888 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007889 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007890 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007891 } else if (audio_is_linear_pcm(out->format) &&
7892 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7893 out->channel_mask = config->channel_mask;
7894 out->sample_rate = config->sample_rate;
7895 out->format = config->format;
7896 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7897 // does this change?
7898 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7899 out->config.rate = config->sample_rate;
7900 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7901 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7902 audio_bytes_per_sample(config->format));
7903 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007904 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307905 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307906 pthread_mutex_lock(&adev->lock);
7907 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7908 pthread_mutex_unlock(&adev->lock);
7909
7910 // reject offload during card offline to allow
7911 // fallback to s/w paths
7912 if (offline) {
7913 ret = -ENODEV;
7914 goto error_open;
7915 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007916
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007917 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7918 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7919 ALOGE("%s: Unsupported Offload information", __func__);
7920 ret = -EINVAL;
7921 goto error_open;
7922 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007923
Atul Khare3fa6e542017-08-09 00:56:17 +05307924 if (config->offload_info.format == 0)
7925 config->offload_info.format = config->format;
7926 if (config->offload_info.sample_rate == 0)
7927 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007928
Mingming Yin90310102013-11-13 16:57:00 -08007929 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307930 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007931 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007932 ret = -EINVAL;
7933 goto error_open;
7934 }
7935
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007936 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7937 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7938 (audio_extn_passthru_is_passthrough_stream(out)) &&
7939 !((config->sample_rate == 48000) ||
7940 (config->sample_rate == 96000) ||
7941 (config->sample_rate == 192000))) {
7942 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7943 __func__, config->sample_rate, config->offload_info.format);
7944 ret = -EINVAL;
7945 goto error_open;
7946 }
7947
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007948 out->compr_config.codec = (struct snd_codec *)
7949 calloc(1, sizeof(struct snd_codec));
7950
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007951 if (!out->compr_config.codec) {
7952 ret = -ENOMEM;
7953 goto error_open;
7954 }
7955
Dhananjay Kumarac341582017-02-23 23:42:25 +05307956 out->stream.pause = out_pause;
7957 out->stream.resume = out_resume;
7958 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307959 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307960 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007961 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307962 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007963 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307964 } else {
7965 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7966 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007967 }
vivek mehta446c3962015-09-14 10:57:35 -07007968
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307969 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7970 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007971#ifdef AUDIO_GKI_ENABLED
7972 /* out->compr_config.codec->reserved[1] is for flags */
7973 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7974#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307975 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007976#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307977 }
7978
vivek mehta446c3962015-09-14 10:57:35 -07007979 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007980 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007981 config->format == 0 && config->sample_rate == 0 &&
7982 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007983 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007984 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7985 } else {
7986 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7987 ret = -EEXIST;
7988 goto error_open;
7989 }
vivek mehta446c3962015-09-14 10:57:35 -07007990 }
7991
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007992 if (config->offload_info.channel_mask)
7993 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007994 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007995 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007996 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007997 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307998 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007999 ret = -EINVAL;
8000 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08008001 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07008002
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008003 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008004 out->sample_rate = config->offload_info.sample_rate;
8005
Mingming Yin3ee55c62014-08-04 14:23:35 -07008006 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008007
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308008 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308009 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308010 audio_extn_dolby_send_ddp_endp_params(adev);
8011 audio_extn_dolby_set_dmid(adev);
8012 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008013
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008014 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008015 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008016 out->compr_config.codec->bit_rate =
8017 config->offload_info.bit_rate;
8018 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308019 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008020 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308021 /* Update bit width only for non passthrough usecases.
8022 * For passthrough usecases, the output will always be opened @16 bit
8023 */
8024 if (!audio_extn_passthru_is_passthrough_stream(out))
8025 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308026
8027 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008028#ifdef AUDIO_GKI_ENABLED
8029 /* out->compr_config.codec->reserved[1] is for flags */
8030 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8031 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8032#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308033 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8034 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008035#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308036
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008037 /*TODO: Do we need to change it for passthrough */
8038 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008039
Manish Dewangana6fc5442015-08-24 20:30:31 +05308040 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8041 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308042 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308043 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308044 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8045 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308046
8047 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8048 AUDIO_FORMAT_PCM) {
8049
8050 /*Based on platform support, configure appropriate alsa format for corresponding
8051 *hal input format.
8052 */
8053 out->compr_config.codec->format = hal_format_to_alsa(
8054 config->offload_info.format);
8055
Ashish Jain83a6cc22016-06-28 14:34:17 +05308056 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308057 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308058 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308059
Dhananjay Kumarac341582017-02-23 23:42:25 +05308060 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308061 *hal input format and alsa format might differ based on platform support.
8062 */
8063 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308064 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308065
8066 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8067
Deeraj Soman93155a62019-09-30 19:00:37 +05308068 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8069 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8070 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8071 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8072 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308073
Ashish Jainf1eaa582016-05-23 20:54:24 +05308074 /* Check if alsa session is configured with the same format as HAL input format,
8075 * if not then derive correct fragment size needed to accomodate the
8076 * conversion of HAL input format to alsa format.
8077 */
8078 audio_extn_utils_update_direct_pcm_fragment_size(out);
8079
8080 /*if hal input and output fragment size is different this indicates HAL input format is
8081 *not same as the alsa format
8082 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308083 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308084 /*Allocate a buffer to convert input data to the alsa configured format.
8085 *size of convert buffer is equal to the size required to hold one fragment size
8086 *worth of pcm data, this is because flinger does not write more than fragment_size
8087 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308088 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8089 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308090 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8091 ret = -ENOMEM;
8092 goto error_open;
8093 }
8094 }
8095 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8096 out->compr_config.fragment_size =
8097 audio_extn_passthru_get_buffer_size(&config->offload_info);
8098 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8099 } else {
8100 out->compr_config.fragment_size =
8101 platform_get_compress_offload_buffer_size(&config->offload_info);
8102 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8103 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008104
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308105 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8106 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8107 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07008108 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308109 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008110
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308111 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8112 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8113 }
8114
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008115 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8116 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008117
Manish Dewangan69426c82017-01-30 17:35:36 +05308118 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8119 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8120 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8121 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8122 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8123 } else {
8124 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8125 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008126
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308127 memset(&out->channel_map_param, 0,
8128 sizeof(struct audio_out_channel_map_param));
8129
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008130 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308131 out->send_next_track_params = false;
8132 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008133 out->offload_state = OFFLOAD_STATE_IDLE;
8134 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008135 out->writeAt.tv_sec = 0;
8136 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008137
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008138 audio_extn_dts_create_state_notifier_node(out->usecase);
8139
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008140 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8141 __func__, config->offload_info.version,
8142 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308143
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308144 /* Check if DSD audio format is supported in codec
8145 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308146 */
8147
8148 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308149 (!platform_check_codec_dsd_support(adev->platform) ||
8150 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308151 ret = -EINVAL;
8152 goto error_open;
8153 }
8154
Ashish Jain5106d362016-05-11 19:23:33 +05308155 /* Disable gapless if any of the following is true
8156 * passthrough playback
8157 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308158 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308159 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308160 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308161 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008162 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308163 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308164 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308165 check_and_set_gapless_mode(adev, false);
8166 } else
8167 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008168
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308169 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008170 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8171 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308172 if (config->format == AUDIO_FORMAT_DSD) {
8173 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008174#ifdef AUDIO_GKI_ENABLED
8175 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8176 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8177#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308178 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008179#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308180 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008181
8182 create_offload_callback_thread(out);
8183
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008184 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008185 switch (config->sample_rate) {
8186 case 0:
8187 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8188 break;
8189 case 8000:
8190 case 16000:
8191 case 48000:
8192 out->sample_rate = config->sample_rate;
8193 break;
8194 default:
8195 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8196 config->sample_rate);
8197 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8198 ret = -EINVAL;
8199 goto error_open;
8200 }
8201 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8202 switch (config->channel_mask) {
8203 case AUDIO_CHANNEL_NONE:
8204 case AUDIO_CHANNEL_OUT_STEREO:
8205 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8206 break;
8207 default:
8208 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8209 config->channel_mask);
8210 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8211 ret = -EINVAL;
8212 goto error_open;
8213 }
8214 switch (config->format) {
8215 case AUDIO_FORMAT_DEFAULT:
8216 case AUDIO_FORMAT_PCM_16_BIT:
8217 out->format = AUDIO_FORMAT_PCM_16_BIT;
8218 break;
8219 default:
8220 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8221 config->format);
8222 config->format = AUDIO_FORMAT_PCM_16_BIT;
8223 ret = -EINVAL;
8224 goto error_open;
8225 }
8226
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308227 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008228 if (ret != 0) {
8229 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008230 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008231 goto error_open;
8232 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008233 } else if (is_single_device_type_equal(&out->device_list,
8234 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008235 switch (config->sample_rate) {
8236 case 0:
8237 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8238 break;
8239 case 8000:
8240 case 16000:
8241 case 48000:
8242 out->sample_rate = config->sample_rate;
8243 break;
8244 default:
8245 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8246 config->sample_rate);
8247 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8248 ret = -EINVAL;
8249 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008250 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008251 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8252 switch (config->channel_mask) {
8253 case AUDIO_CHANNEL_NONE:
8254 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8255 break;
8256 case AUDIO_CHANNEL_OUT_STEREO:
8257 out->channel_mask = config->channel_mask;
8258 break;
8259 default:
8260 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8261 config->channel_mask);
8262 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8263 ret = -EINVAL;
8264 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008265 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008266 switch (config->format) {
8267 case AUDIO_FORMAT_DEFAULT:
8268 out->format = AUDIO_FORMAT_PCM_16_BIT;
8269 break;
8270 case AUDIO_FORMAT_PCM_16_BIT:
8271 out->format = config->format;
8272 break;
8273 default:
8274 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8275 config->format);
8276 config->format = AUDIO_FORMAT_PCM_16_BIT;
8277 ret = -EINVAL;
8278 break;
8279 }
8280 if (ret != 0)
8281 goto error_open;
8282
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008283 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8284 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008285 out->config.rate = out->sample_rate;
8286 out->config.channels =
8287 audio_channel_count_from_out_mask(out->channel_mask);
8288 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008289 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008290 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308291 unsigned int channels = 0;
8292 /*Update config params to default if not set by the caller*/
8293 if (config->sample_rate == 0)
8294 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8295 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8296 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8297 if (config->format == AUDIO_FORMAT_DEFAULT)
8298 config->format = AUDIO_FORMAT_PCM_16_BIT;
8299
8300 channels = audio_channel_count_from_out_mask(out->channel_mask);
8301
Varun Balaraje49253e2017-07-06 19:48:56 +05308302 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8303 out->usecase = get_interactive_usecase(adev);
8304 out->config = pcm_config_low_latency;
8305 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308306 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008307 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8308 out->flags);
8309 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008310 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8311 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8312 out->config = pcm_config_mmap_playback;
8313 out->stream.start = out_start;
8314 out->stream.stop = out_stop;
8315 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8316 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308317 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8318 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008319 out->hal_output_suspend_supported =
8320 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8321 out->dynamic_pm_qos_config_supported =
8322 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8323 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008324 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8325 } else {
8326 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8327 //the mixer path will be a string similar to "low-latency-playback resume"
8328 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8329 strlcat(out->pm_qos_mixer_path,
8330 " resume", MAX_MIXER_PATH_LEN);
8331 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8332 out->pm_qos_mixer_path);
8333 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308334 out->config = pcm_config_low_latency;
8335 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8336 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8337 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308338 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8339 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8340 if (out->config.period_size <= 0) {
8341 ALOGE("Invalid configuration period size is not valid");
8342 ret = -EINVAL;
8343 goto error_open;
8344 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008345 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8346 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8347 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008348 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8349 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8350 out->config = pcm_config_haptics_audio;
8351 if (force_haptic_path)
8352 adev->haptics_config = pcm_config_haptics_audio;
8353 else
8354 adev->haptics_config = pcm_config_haptics;
8355
Meng Wangd08ce322020-04-02 08:59:20 +08008356 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008357 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8358
8359 if (force_haptic_path) {
8360 out->config.channels = 1;
8361 adev->haptics_config.channels = 1;
8362 } else
8363 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 -08008364 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008365 ret = audio_extn_auto_hal_open_output_stream(out);
8366 if (ret) {
8367 ALOGE("%s: Failed to open output stream for bus device", __func__);
8368 ret = -EINVAL;
8369 goto error_open;
8370 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308371 } else {
8372 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008373 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8374 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308375 }
8376 out->hal_ip_format = format = out->format;
8377 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8378 out->hal_op_format = pcm_format_to_hal(out->config.format);
8379 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8380 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008381 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308382 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308383 if (out->hal_ip_format != out->hal_op_format) {
8384 uint32_t buffer_size = out->config.period_size *
8385 format_to_bitwidth_table[out->hal_op_format] *
8386 out->config.channels;
8387 out->convert_buffer = calloc(1, buffer_size);
8388 if (out->convert_buffer == NULL){
8389 ALOGE("Allocation failed for convert buffer for size %d",
8390 out->compr_config.fragment_size);
8391 ret = -ENOMEM;
8392 goto error_open;
8393 }
8394 ALOGD("Convert buffer allocated of size %d", buffer_size);
8395 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008396 }
8397
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008398 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8399 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308400
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008401 /* TODO remove this hardcoding and check why width is zero*/
8402 if (out->bit_width == 0)
8403 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308404 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008405 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008406 &out->device_list, out->flags,
8407 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308408 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308409 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008410 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008411 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8412 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008413 if(adev->primary_output == NULL)
8414 adev->primary_output = out;
8415 else {
8416 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008417 ret = -EEXIST;
8418 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008419 }
8420 }
8421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008422 /* Check if this usecase is already existing */
8423 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008424 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8425 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008426 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008427 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008428 ret = -EEXIST;
8429 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008430 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008431
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008432 pthread_mutex_unlock(&adev->lock);
8433
8434 out->stream.common.get_sample_rate = out_get_sample_rate;
8435 out->stream.common.set_sample_rate = out_set_sample_rate;
8436 out->stream.common.get_buffer_size = out_get_buffer_size;
8437 out->stream.common.get_channels = out_get_channels;
8438 out->stream.common.get_format = out_get_format;
8439 out->stream.common.set_format = out_set_format;
8440 out->stream.common.standby = out_standby;
8441 out->stream.common.dump = out_dump;
8442 out->stream.common.set_parameters = out_set_parameters;
8443 out->stream.common.get_parameters = out_get_parameters;
8444 out->stream.common.add_audio_effect = out_add_audio_effect;
8445 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8446 out->stream.get_latency = out_get_latency;
8447 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008448#ifdef NO_AUDIO_OUT
8449 out->stream.write = out_write_for_no_output;
8450#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008451 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008452#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008453 out->stream.get_render_position = out_get_render_position;
8454 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008455 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008456
Haynes Mathew George16081042017-05-31 17:16:49 -07008457 if (out->realtime)
8458 out->af_period_multiplier = af_period_multiplier;
8459 else
8460 out->af_period_multiplier = 1;
8461
Andy Hunga1f48fa2019-07-01 18:14:53 -07008462 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008464 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008465 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008466 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008467
8468 config->format = out->stream.common.get_format(&out->stream.common);
8469 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8470 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308471 register_format(out->format, out->supported_formats);
8472 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8473 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008474
Aalique Grahame22e49102018-12-18 14:23:57 -08008475 out->error_log = error_log_create(
8476 ERROR_LOG_ENTRIES,
8477 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8478
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308479 /*
8480 By locking output stream before registering, we allow the callback
8481 to update stream's state only after stream's initial state is set to
8482 adev state.
8483 */
8484 lock_output_stream(out);
8485 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8486 pthread_mutex_lock(&adev->lock);
8487 out->card_status = adev->card_status;
8488 pthread_mutex_unlock(&adev->lock);
8489 pthread_mutex_unlock(&out->lock);
8490
Aalique Grahame22e49102018-12-18 14:23:57 -08008491 stream_app_type_cfg_init(&out->app_type_cfg);
8492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008493 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308494 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008495 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008496
8497 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8498 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8499 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008500 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308501 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008502 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008503 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308504 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8505 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008506 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8507 out->usecase, PCM_PLAYBACK);
8508 hdlr_stream_cfg.flags = out->flags;
8509 hdlr_stream_cfg.type = PCM_PLAYBACK;
8510 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8511 &hdlr_stream_cfg);
8512 if (ret) {
8513 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8514 out->adsp_hdlr_stream_handle = NULL;
8515 }
8516 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308517 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8518 is_direct_passthough, false);
8519 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8520 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008521 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008522 if (ret < 0) {
8523 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8524 out->ip_hdlr_handle = NULL;
8525 }
8526 }
Derek Chenf939fb72018-11-13 13:34:41 -08008527
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008528 ret = io_streams_map_insert(adev, &out->stream.common,
8529 out->handle, AUDIO_PATCH_HANDLE_NONE);
8530 if (ret != 0)
8531 goto error_open;
8532
Derek Chenf939fb72018-11-13 13:34:41 -08008533 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8534 calloc(1, sizeof(streams_output_ctxt_t));
8535 if (out_ctxt == NULL) {
8536 ALOGE("%s fail to allocate output ctxt", __func__);
8537 ret = -ENOMEM;
8538 goto error_open;
8539 }
8540 out_ctxt->output = out;
8541
8542 pthread_mutex_lock(&adev->lock);
8543 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8544 pthread_mutex_unlock(&adev->lock);
8545
Eric Laurent994a6932013-07-17 11:51:42 -07008546 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008547 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008548
8549error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308550 if (out->convert_buffer)
8551 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008552 free(out);
8553 *stream_out = NULL;
8554 ALOGD("%s: exit: ret %d", __func__, ret);
8555 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008556}
8557
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308558void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008559 struct audio_stream_out *stream)
8560{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008561 struct stream_out *out = (struct stream_out *)stream;
8562 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008563 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008564
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008565 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308566
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008567 io_streams_map_remove(adev, out->handle);
8568
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308569 // must deregister from sndmonitor first to prevent races
8570 // between the callback and close_stream
8571 audio_extn_snd_mon_unregister_listener(out);
8572
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008573 /* close adsp hdrl session before standby */
8574 if (out->adsp_hdlr_stream_handle) {
8575 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8576 if (ret)
8577 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8578 out->adsp_hdlr_stream_handle = NULL;
8579 }
8580
Manish Dewangan21a850a2017-08-14 12:03:55 +05308581 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008582 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8583 out->ip_hdlr_handle = NULL;
8584 }
8585
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008586 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308587 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008588 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308589 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308590 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008591 if(ret != 0)
8592 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8593 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008594 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008595 out_standby(&stream->common);
8596
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008597 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008598 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008599 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008600 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008601 if (out->compr_config.codec != NULL)
8602 free(out->compr_config.codec);
8603 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008604
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308605 out->a2dp_compress_mute = false;
8606
Varun Balaraje49253e2017-07-06 19:48:56 +05308607 if (is_interactive_usecase(out->usecase))
8608 free_interactive_usecase(adev, out->usecase);
8609
Ashish Jain83a6cc22016-06-28 14:34:17 +05308610 if (out->convert_buffer != NULL) {
8611 free(out->convert_buffer);
8612 out->convert_buffer = NULL;
8613 }
8614
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008615 if (adev->voice_tx_output == out)
8616 adev->voice_tx_output = NULL;
8617
Aalique Grahame22e49102018-12-18 14:23:57 -08008618 error_log_destroy(out->error_log);
8619 out->error_log = NULL;
8620
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308621 if (adev->primary_output == out)
8622 adev->primary_output = NULL;
8623
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008624 pthread_cond_destroy(&out->cond);
8625 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008626
8627 pthread_mutex_lock(&adev->lock);
8628 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8629 if (out_ctxt != NULL) {
8630 list_remove(&out_ctxt->list);
8631 free(out_ctxt);
8632 } else {
8633 ALOGW("%s, output stream already closed", __func__);
8634 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008635 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008636 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008637 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008638}
8639
8640static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8641{
8642 struct audio_device *adev = (struct audio_device *)dev;
8643 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008644 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008645 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008646 int ret;
8647 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008648 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008649 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008650 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008651
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008652 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008653 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008654
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308655 if (!parms)
8656 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308657
Derek Chen6f293672019-04-01 01:40:24 -07008658 /* notify adev and input/output streams on the snd card status */
8659 adev_snd_mon_cb((void *)adev, parms);
8660
8661 list_for_each(node, &adev->active_outputs_list) {
8662 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8663 streams_output_ctxt_t,
8664 list);
8665 out_snd_mon_cb((void *)out_ctxt->output, parms);
8666 }
8667
8668 list_for_each(node, &adev->active_inputs_list) {
8669 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8670 streams_input_ctxt_t,
8671 list);
8672 in_snd_mon_cb((void *)in_ctxt->input, parms);
8673 }
8674
Zhou Songd6d71752019-05-21 18:08:51 +08008675 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308676 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8677 if (ret >= 0) {
8678 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008679 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308680 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008681 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308682 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008683 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008684 }
8685 }
8686
8687 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8688 if (ret>=0) {
8689 if (!strncmp(value, "false", 5) &&
8690 audio_extn_a2dp_source_is_suspended()) {
8691 struct audio_usecase *usecase;
8692 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008693 list_for_each(node, &adev->usecase_list) {
8694 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008695 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008696 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008697 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008698 reassign_device_list(&usecase->stream.in->device_list,
8699 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008700 select_devices(adev, usecase->id);
8701 }
Zhou Songd6d71752019-05-21 18:08:51 +08008702 }
8703 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308704 }
8705
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008706 status = voice_set_parameters(adev, parms);
8707 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008708 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008709
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008710 status = platform_set_parameters(adev->platform, parms);
8711 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008712 goto done;
8713
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008714 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8715 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008716 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008717 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8718 adev->bluetooth_nrec = true;
8719 else
8720 adev->bluetooth_nrec = false;
8721 }
8722
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008723 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8724 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008725 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8726 adev->screen_off = false;
8727 else
8728 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008729 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008730 }
8731
Eric Laurent4b084132018-10-19 17:33:43 -07008732 ret = str_parms_get_int(parms, "rotation", &val);
8733 if (ret >= 0) {
8734 bool reverse_speakers = false;
8735 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8736 switch (val) {
8737 // FIXME: note that the code below assumes that the speakers are in the correct placement
8738 // relative to the user when the device is rotated 90deg from its default rotation. This
8739 // assumption is device-specific, not platform-specific like this code.
8740 case 270:
8741 reverse_speakers = true;
8742 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8743 break;
8744 case 0:
8745 case 180:
8746 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8747 break;
8748 case 90:
8749 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8750 break;
8751 default:
8752 ALOGE("%s: unexpected rotation of %d", __func__, val);
8753 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008754 }
Eric Laurent4b084132018-10-19 17:33:43 -07008755 if (status == 0) {
8756 // check and set swap
8757 // - check if orientation changed and speaker active
8758 // - set rotation and cache the rotation value
8759 adev->camera_orientation =
8760 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8761 if (!audio_extn_is_maxx_audio_enabled())
8762 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8763 }
8764 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008765
Mingming Yin514a8bc2014-07-29 15:22:21 -07008766 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8767 if (ret >= 0) {
8768 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8769 adev->bt_wb_speech_enabled = true;
8770 else
8771 adev->bt_wb_speech_enabled = false;
8772 }
8773
Zhou Song12c29502019-03-16 10:37:18 +08008774 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8775 if (ret >= 0) {
8776 val = atoi(value);
8777 adev->swb_speech_mode = val;
8778 }
8779
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008780 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8781 if (ret >= 0) {
8782 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308783 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008784 if (audio_is_output_device(val) &&
8785 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008786 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008787 platform_get_controller_stream_from_params(parms, &controller, &stream);
8788 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8789 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008790 if (ret < 0) {
8791 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308792 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008793 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008794 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308795 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008796 /*
8797 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8798 * Per AudioPolicyManager, USB device is higher priority than WFD.
8799 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8800 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8801 * starting voice call on USB
8802 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008803 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308804 if (ret >= 0)
8805 audio_extn_usb_add_device(device, atoi(value));
8806
Zhou Song6f862822017-11-06 17:27:57 +08008807 if (!audio_extn_usb_is_tunnel_supported()) {
8808 ALOGV("detected USB connect .. disable proxy");
8809 adev->allow_afe_proxy_usage = false;
8810 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008811 }
8812 }
8813
8814 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8815 if (ret >= 0) {
8816 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308817 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008818 /*
8819 * The HDMI / Displayport disconnect handling has been moved to
8820 * audio extension to ensure that its parameters are not
8821 * invalidated prior to updating sysfs of the disconnect event
8822 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8823 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308824 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008825 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308826 if (ret >= 0)
8827 audio_extn_usb_remove_device(device, atoi(value));
8828
Zhou Song6f862822017-11-06 17:27:57 +08008829 if (!audio_extn_usb_is_tunnel_supported()) {
8830 ALOGV("detected USB disconnect .. enable proxy");
8831 adev->allow_afe_proxy_usage = true;
8832 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008833 }
8834 }
8835
Aalique Grahame22e49102018-12-18 14:23:57 -08008836 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008837 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008838
8839 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008840 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308841 struct audio_usecase *usecase;
8842 struct listnode *node;
8843 list_for_each(node, &adev->usecase_list) {
8844 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008845 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8846 continue;
8847
8848 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308849 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008850 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308851 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008852 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308853 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308854 ALOGD("Switching to speaker and muting the stream before select_devices");
8855 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308856 //force device switch to re configure encoder
8857 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308858 ALOGD("Unmuting the stream after select_devices");
8859 usecase->stream.out->a2dp_compress_mute = false;
8860 out_set_compr_volume(&usecase->stream.out->stream, usecase->stream.out->volume_l, usecase->stream.out->volume_r);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308861 audio_extn_a2dp_set_handoff_mode(false);
8862 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308863 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308864 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8865 usecase->stream.out->a2dp_compress_mute) {
8866 pthread_mutex_unlock(&adev->lock);
8867 lock_output_stream(usecase->stream.out);
8868 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008869 reassign_device_list(&usecase->stream.out->device_list,
8870 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308871 check_a2dp_restore_l(adev, usecase->stream.out, true);
8872 pthread_mutex_unlock(&usecase->stream.out->lock);
8873 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308874 }
8875 }
8876 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008877
8878 //handle vr audio setparam
8879 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8880 value, sizeof(value));
8881 if (ret >= 0) {
8882 ALOGI("Setting vr mode to be %s", value);
8883 if (!strncmp(value, "true", 4)) {
8884 adev->vr_audio_mode_enabled = true;
8885 ALOGI("Setting vr mode to true");
8886 } else if (!strncmp(value, "false", 5)) {
8887 adev->vr_audio_mode_enabled = false;
8888 ALOGI("Setting vr mode to false");
8889 } else {
8890 ALOGI("wrong vr mode set");
8891 }
8892 }
8893
Eric Laurent4b084132018-10-19 17:33:43 -07008894 //FIXME: to be replaced by proper video capture properties API
8895 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8896 if (ret >= 0) {
8897 int camera_facing = CAMERA_FACING_BACK;
8898 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8899 camera_facing = CAMERA_FACING_FRONT;
8900 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8901 camera_facing = CAMERA_FACING_BACK;
8902 else {
8903 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8904 goto done;
8905 }
8906 adev->camera_orientation =
8907 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8908 struct audio_usecase *usecase;
8909 struct listnode *node;
8910 list_for_each(node, &adev->usecase_list) {
8911 usecase = node_to_item(node, struct audio_usecase, list);
8912 struct stream_in *in = usecase->stream.in;
8913 if (usecase->type == PCM_CAPTURE && in != NULL &&
8914 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8915 select_devices(adev, in->usecase);
8916 }
8917 }
8918 }
8919
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308920 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008921done:
8922 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008923 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308924error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008925 ALOGV("%s: exit with code(%d)", __func__, status);
8926 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008927}
8928
8929static char* adev_get_parameters(const struct audio_hw_device *dev,
8930 const char *keys)
8931{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308932 ALOGD("%s:%s", __func__, keys);
8933
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008934 struct audio_device *adev = (struct audio_device *)dev;
8935 struct str_parms *reply = str_parms_create();
8936 struct str_parms *query = str_parms_create_str(keys);
8937 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308938 char value[256] = {0};
8939 int ret = 0;
8940
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008941 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008942 if (reply) {
8943 str_parms_destroy(reply);
8944 }
8945 if (query) {
8946 str_parms_destroy(query);
8947 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008948 ALOGE("adev_get_parameters: failed to create query or reply");
8949 return NULL;
8950 }
8951
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008952 //handle vr audio getparam
8953
8954 ret = str_parms_get_str(query,
8955 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8956 value, sizeof(value));
8957
8958 if (ret >= 0) {
8959 bool vr_audio_enabled = false;
8960 pthread_mutex_lock(&adev->lock);
8961 vr_audio_enabled = adev->vr_audio_mode_enabled;
8962 pthread_mutex_unlock(&adev->lock);
8963
8964 ALOGI("getting vr mode to %d", vr_audio_enabled);
8965
8966 if (vr_audio_enabled) {
8967 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8968 "true");
8969 goto exit;
8970 } else {
8971 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8972 "false");
8973 goto exit;
8974 }
8975 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008976
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008977 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008978 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008979 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008980 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008981 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08008982 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308983 pthread_mutex_unlock(&adev->lock);
8984
Naresh Tannirud7205b62014-06-20 02:54:48 +05308985exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008986 str = str_parms_to_str(reply);
8987 str_parms_destroy(query);
8988 str_parms_destroy(reply);
8989
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308990 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008991 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008992}
8993
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008994static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008995{
8996 return 0;
8997}
8998
8999static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
9000{
Haynes Mathew George5191a852013-09-11 14:19:36 -07009001 int ret;
9002 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08009003
9004 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
9005
Haynes Mathew George5191a852013-09-11 14:19:36 -07009006 pthread_mutex_lock(&adev->lock);
9007 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009008 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009009 pthread_mutex_unlock(&adev->lock);
9010 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009011}
9012
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009013static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9014 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009015{
9016 return -ENOSYS;
9017}
9018
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009019static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9020 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009021{
9022 return -ENOSYS;
9023}
9024
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009025static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9026 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009027{
9028 return -ENOSYS;
9029}
9030
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009031static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9032 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009033{
9034 return -ENOSYS;
9035}
9036
9037static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9038{
9039 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009040 struct listnode *node;
9041 struct audio_usecase *usecase = NULL;
9042 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009044 pthread_mutex_lock(&adev->lock);
9045 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309046 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9047 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009048 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05309049 if( mode == AUDIO_MODE_CALL_SCREEN ){
9050 adev->current_call_output = adev->primary_output;
9051 voice_start_call(adev);
9052 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009053 (mode == AUDIO_MODE_NORMAL ||
9054 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009055 list_for_each(node, &adev->usecase_list) {
9056 usecase = node_to_item(node, struct audio_usecase, list);
9057 if (usecase->type == VOICE_CALL)
9058 break;
9059 }
9060 if (usecase &&
9061 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9062 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9063 true);
9064 if (ret != 0) {
9065 /* default service interval was successfully updated,
9066 reopen USB backend with new service interval */
9067 check_usecases_codec_backend(adev,
9068 usecase,
9069 usecase->out_snd_device);
9070 }
9071 }
9072
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009073 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009074 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009075 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009076 // restore device for other active usecases after stop call
9077 list_for_each(node, &adev->usecase_list) {
9078 usecase = node_to_item(node, struct audio_usecase, list);
9079 select_devices(adev, usecase->id);
9080 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009081 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009082 }
9083 pthread_mutex_unlock(&adev->lock);
9084 return 0;
9085}
9086
9087static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9088{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009089 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009090 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009091
9092 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009093 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009094 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009095
Derek Chend2530072014-11-24 12:39:14 -08009096 if (adev->ext_hw_plugin)
9097 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009098
9099 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009100 pthread_mutex_unlock(&adev->lock);
9101
9102 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009103}
9104
9105static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9106{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009107 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009108 return 0;
9109}
9110
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009111static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009112 const struct audio_config *config)
9113{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009114 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009115
Aalique Grahame22e49102018-12-18 14:23:57 -08009116 /* Don't know if USB HIFI in this context so use true to be conservative */
9117 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9118 true /*is_usb_hifi */) != 0)
9119 return 0;
9120
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009121 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9122 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009123}
9124
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009125static bool adev_input_allow_hifi_record(struct audio_device *adev,
9126 audio_devices_t devices,
9127 audio_input_flags_t flags,
9128 audio_source_t source) {
9129 const bool allowed = true;
9130
9131 if (!audio_is_usb_in_device(devices))
9132 return !allowed;
9133
9134 switch (flags) {
9135 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009136 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009137 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9138 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009139 default:
9140 return !allowed;
9141 }
9142
9143 switch (source) {
9144 case AUDIO_SOURCE_DEFAULT:
9145 case AUDIO_SOURCE_MIC:
9146 case AUDIO_SOURCE_UNPROCESSED:
9147 break;
9148 default:
9149 return !allowed;
9150 }
9151
9152 switch (adev->mode) {
9153 case 0:
9154 break;
9155 default:
9156 return !allowed;
9157 }
9158
9159 return allowed;
9160}
9161
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009162static int adev_update_voice_comm_input_stream(struct stream_in *in,
9163 struct audio_config *config)
9164{
9165 bool valid_rate = (config->sample_rate == 8000 ||
9166 config->sample_rate == 16000 ||
9167 config->sample_rate == 32000 ||
9168 config->sample_rate == 48000);
9169 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9170
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009171 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009172 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009173 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9174 in->config = default_pcm_config_voip_copp;
9175 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9176 DEFAULT_VOIP_BUF_DURATION_MS,
9177 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009178 } else {
9179 ALOGW("%s No valid input in voip, use defaults"
9180 "sample rate %u, channel mask 0x%X",
9181 __func__, config->sample_rate, in->channel_mask);
9182 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009183 in->config.rate = config->sample_rate;
9184 in->sample_rate = config->sample_rate;
9185 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009186 //XXX needed for voice_extn_compress_voip_open_input_stream
9187 in->config.rate = config->sample_rate;
9188 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309189 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009190 voice_extn_compress_voip_is_active(in->dev)) &&
9191 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9192 valid_rate && valid_ch) {
9193 voice_extn_compress_voip_open_input_stream(in);
9194 // update rate entries to match config from AF
9195 in->config.rate = config->sample_rate;
9196 in->sample_rate = config->sample_rate;
9197 } else {
9198 ALOGW("%s compress voip not active, use defaults", __func__);
9199 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009200 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009201 return 0;
9202}
9203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009204static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009205 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009206 audio_devices_t devices,
9207 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009208 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309209 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009210 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009211 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009212{
9213 struct audio_device *adev = (struct audio_device *)dev;
9214 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009215 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009216 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009217 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309218 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009219 bool is_usb_dev = audio_is_usb_in_device(devices);
9220 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9221 devices,
9222 flags,
9223 source);
Andy Hung94320602018-10-29 18:31:12 -07009224 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9225 " sample_rate %u, channel_mask %#x, format %#x",
9226 __func__, flags, is_usb_dev, may_use_hifi_record,
9227 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309228
kunleizdff872d2018-08-20 14:40:33 +08009229 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009230 is_usb_dev = false;
9231 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9232 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9233 __func__, devices);
9234 }
9235
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009236 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009237
9238 if (!(is_usb_dev && may_use_hifi_record)) {
9239 if (config->sample_rate == 0)
9240 config->sample_rate = 48000;
9241 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9242 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9243 if (config->format == AUDIO_FORMAT_DEFAULT)
9244 config->format = AUDIO_FORMAT_PCM_16_BIT;
9245
9246 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9247
Aalique Grahame22e49102018-12-18 14:23:57 -08009248 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9249 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009250 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309251 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009252
Rahul Sharma99770982019-03-06 17:05:26 +05309253 pthread_mutex_lock(&adev->lock);
9254 if (in_get_stream(adev, handle) != NULL) {
9255 ALOGW("%s, input stream already opened", __func__);
9256 ret = -EEXIST;
9257 }
9258 pthread_mutex_unlock(&adev->lock);
9259 if (ret)
9260 return ret;
9261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009262 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009263
9264 if (!in) {
9265 ALOGE("failed to allocate input stream");
9266 return -ENOMEM;
9267 }
9268
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309269 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309270 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9271 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009272 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009273 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009275 in->stream.common.get_sample_rate = in_get_sample_rate;
9276 in->stream.common.set_sample_rate = in_set_sample_rate;
9277 in->stream.common.get_buffer_size = in_get_buffer_size;
9278 in->stream.common.get_channels = in_get_channels;
9279 in->stream.common.get_format = in_get_format;
9280 in->stream.common.set_format = in_set_format;
9281 in->stream.common.standby = in_standby;
9282 in->stream.common.dump = in_dump;
9283 in->stream.common.set_parameters = in_set_parameters;
9284 in->stream.common.get_parameters = in_get_parameters;
9285 in->stream.common.add_audio_effect = in_add_audio_effect;
9286 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9287 in->stream.set_gain = in_set_gain;
9288 in->stream.read = in_read;
9289 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009290 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309291 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009292 in->stream.set_microphone_direction = in_set_microphone_direction;
9293 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009294 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009295
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009296 list_init(&in->device_list);
9297 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009298 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009299 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009300 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009301 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009302 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009303 in->bit_width = 16;
9304 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009305 in->direction = MIC_DIRECTION_UNSPECIFIED;
9306 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009307 list_init(&in->aec_list);
9308 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009309 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009310
Andy Hung94320602018-10-29 18:31:12 -07009311 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009312 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9313 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9314 /* Force channel config requested to mono if incall
9315 record is being requested for only uplink/downlink */
9316 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9317 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9318 ret = -EINVAL;
9319 goto err_open;
9320 }
9321 }
9322
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009323 if (is_usb_dev && may_use_hifi_record) {
9324 /* HiFi record selects an appropriate format, channel, rate combo
9325 depending on sink capabilities*/
9326 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9327 &config->format,
9328 &in->supported_formats[0],
9329 MAX_SUPPORTED_FORMATS,
9330 &config->channel_mask,
9331 &in->supported_channel_masks[0],
9332 MAX_SUPPORTED_CHANNEL_MASKS,
9333 &config->sample_rate,
9334 &in->supported_sample_rates[0],
9335 MAX_SUPPORTED_SAMPLE_RATES);
9336 if (ret != 0) {
9337 ret = -EINVAL;
9338 goto err_open;
9339 }
9340 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009341 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309342 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309343 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9344 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9345 in->config.format = PCM_FORMAT_S32_LE;
9346 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309347 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9348 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9349 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9350 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9351 bool ret_error = false;
9352 in->bit_width = 24;
9353 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9354 from HAL is 24_packed and 8_24
9355 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9356 24_packed return error indicating supported format is 24_packed
9357 *> In case of any other source requesting 24 bit or float return error
9358 indicating format supported is 16 bit only.
9359
9360 on error flinger will retry with supported format passed
9361 */
9362 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9363 (source != AUDIO_SOURCE_CAMCORDER)) {
9364 config->format = AUDIO_FORMAT_PCM_16_BIT;
9365 if (config->sample_rate > 48000)
9366 config->sample_rate = 48000;
9367 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009368 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9369 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309370 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9371 ret_error = true;
9372 }
9373
9374 if (ret_error) {
9375 ret = -EINVAL;
9376 goto err_open;
9377 }
9378 }
9379
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009380 in->channel_mask = config->channel_mask;
9381 in->format = config->format;
9382
9383 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309384
9385 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9386 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9387 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9388 else {
9389 ret = -EINVAL;
9390 goto err_open;
9391 }
9392 }
9393
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009394 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309395 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9396 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009397 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9398 is_low_latency = true;
9399#if LOW_LATENCY_CAPTURE_USE_CASE
9400 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9401#endif
9402 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009403 if (!in->realtime) {
9404 in->config = pcm_config_audio_capture;
9405 frame_size = audio_stream_in_frame_size(&in->stream);
9406 buffer_size = get_input_buffer_size(config->sample_rate,
9407 config->format,
9408 channel_count,
9409 is_low_latency);
9410 in->config.period_size = buffer_size / frame_size;
9411 in->config.rate = config->sample_rate;
9412 in->af_period_multiplier = 1;
9413 } else {
9414 // period size is left untouched for rt mode playback
9415 in->config = pcm_config_audio_capture_rt;
9416 in->af_period_multiplier = af_period_multiplier;
9417 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009418 }
9419
9420 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9421 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9422 in->realtime = 0;
9423 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9424 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009425 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009426 in->stream.start = in_start;
9427 in->stream.stop = in_stop;
9428 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9429 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009430 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009431 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009432 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9433 in->config = pcm_config_audio_capture;
9434 frame_size = audio_stream_in_frame_size(&in->stream);
9435 buffer_size = get_input_buffer_size(config->sample_rate,
9436 config->format,
9437 channel_count,
9438 false /*is_low_latency*/);
9439 in->config.period_size = buffer_size / frame_size;
9440 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009441 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009442 switch (config->format) {
9443 case AUDIO_FORMAT_PCM_32_BIT:
9444 in->bit_width = 32;
9445 break;
9446 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9447 case AUDIO_FORMAT_PCM_8_24_BIT:
9448 in->bit_width = 24;
9449 break;
9450 default:
9451 in->bit_width = 16;
9452 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009453 } else if (is_single_device_type_equal(&in->device_list,
9454 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9455 is_single_device_type_equal(&in->device_list,
9456 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009457 if (config->sample_rate == 0)
9458 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9459 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9460 config->sample_rate != 8000) {
9461 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9462 ret = -EINVAL;
9463 goto err_open;
9464 }
9465 if (config->format == AUDIO_FORMAT_DEFAULT)
9466 config->format = AUDIO_FORMAT_PCM_16_BIT;
9467 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9468 config->format = AUDIO_FORMAT_PCM_16_BIT;
9469 ret = -EINVAL;
9470 goto err_open;
9471 }
9472
9473 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009474 if (adev->ha_proxy_enable &&
9475 is_single_device_type_equal(&in->device_list,
9476 AUDIO_DEVICE_IN_TELEPHONY_RX))
9477 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009478 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009479 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009480 in->af_period_multiplier = 1;
9481 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9482 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9483 (config->sample_rate == 8000 ||
9484 config->sample_rate == 16000 ||
9485 config->sample_rate == 32000 ||
9486 config->sample_rate == 48000) &&
9487 channel_count == 1) {
9488 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9489 in->config = pcm_config_audio_capture;
9490 frame_size = audio_stream_in_frame_size(&in->stream);
9491 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9492 config->sample_rate,
9493 config->format,
9494 channel_count, false /*is_low_latency*/);
9495 in->config.period_size = buffer_size / frame_size;
9496 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9497 in->config.rate = config->sample_rate;
9498 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009499 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309500 int ret_val;
9501 pthread_mutex_lock(&adev->lock);
9502 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9503 in, config, &channel_mask_updated);
9504 pthread_mutex_unlock(&adev->lock);
9505
9506 if (!ret_val) {
9507 if (channel_mask_updated == true) {
9508 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9509 __func__, config->channel_mask);
9510 ret = -EINVAL;
9511 goto err_open;
9512 }
9513 ALOGD("%s: created multi-channel session succesfully",__func__);
9514 } else if (audio_extn_compr_cap_enabled() &&
9515 audio_extn_compr_cap_format_supported(config->format) &&
9516 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9517 audio_extn_compr_cap_init(in);
9518 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309519 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309520 if (ret)
9521 goto err_open;
9522 } else {
9523 in->config = pcm_config_audio_capture;
9524 in->config.rate = config->sample_rate;
9525 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309526 in->format = config->format;
9527 frame_size = audio_stream_in_frame_size(&in->stream);
9528 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009529 config->format,
9530 channel_count,
9531 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009532 /* prevent division-by-zero */
9533 if (frame_size == 0) {
9534 ALOGE("%s: Error frame_size==0", __func__);
9535 ret = -EINVAL;
9536 goto err_open;
9537 }
9538
Revathi Uddarajud2634032017-12-07 14:42:34 +05309539 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009540 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009541
Revathi Uddarajud2634032017-12-07 14:42:34 +05309542 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9543 /* optionally use VOIP usecase depending on config(s) */
9544 ret = adev_update_voice_comm_input_stream(in, config);
9545 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009546
Revathi Uddarajud2634032017-12-07 14:42:34 +05309547 if (ret) {
9548 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9549 goto err_open;
9550 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009551 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309552
9553 /* assign concurrent capture usecase if record has to caried out from
9554 * actual hardware input source */
9555 if (audio_extn_is_concurrent_capture_enabled() &&
9556 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309557 /* Acquire lock to avoid two concurrent use cases initialized to
9558 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009559
Samyak Jainc37062f2019-04-25 18:41:06 +05309560 if (in->usecase == USECASE_AUDIO_RECORD) {
9561 pthread_mutex_lock(&adev->lock);
9562 if (!(adev->pcm_record_uc_state)) {
9563 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9564 adev->pcm_record_uc_state = 1;
9565 pthread_mutex_unlock(&adev->lock);
9566 } else {
9567 pthread_mutex_unlock(&adev->lock);
9568 /* Assign compress record use case for second record */
9569 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9570 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9571 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9572 if (audio_extn_cin_applicable_stream(in)) {
9573 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309574 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309575 if (ret)
9576 goto err_open;
9577 }
9578 }
9579 }
kunleiz28c73e72019-03-27 17:24:04 +08009580 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009581 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309582 if (audio_extn_ssr_get_stream() != in)
9583 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009584
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009585 in->sample_rate = in->config.rate;
9586
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309587 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9588 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009589 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009590 in->sample_rate, in->bit_width,
9591 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309592 register_format(in->format, in->supported_formats);
9593 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9594 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309595
Aalique Grahame22e49102018-12-18 14:23:57 -08009596 in->error_log = error_log_create(
9597 ERROR_LOG_ENTRIES,
9598 1000000000 /* aggregate consecutive identical errors within one second */);
9599
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009600 /* This stream could be for sound trigger lab,
9601 get sound trigger pcm if present */
9602 audio_extn_sound_trigger_check_and_get_session(in);
9603
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309604 lock_input_stream(in);
9605 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9606 pthread_mutex_lock(&adev->lock);
9607 in->card_status = adev->card_status;
9608 pthread_mutex_unlock(&adev->lock);
9609 pthread_mutex_unlock(&in->lock);
9610
Aalique Grahame22e49102018-12-18 14:23:57 -08009611 stream_app_type_cfg_init(&in->app_type_cfg);
9612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009613 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009614
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009615 ret = io_streams_map_insert(adev, &in->stream.common,
9616 handle, AUDIO_PATCH_HANDLE_NONE);
9617 if (ret != 0)
9618 goto err_open;
9619
Derek Chenf939fb72018-11-13 13:34:41 -08009620 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9621 calloc(1, sizeof(streams_input_ctxt_t));
9622 if (in_ctxt == NULL) {
9623 ALOGE("%s fail to allocate input ctxt", __func__);
9624 ret = -ENOMEM;
9625 goto err_open;
9626 }
9627 in_ctxt->input = in;
9628
9629 pthread_mutex_lock(&adev->lock);
9630 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9631 pthread_mutex_unlock(&adev->lock);
9632
Eric Laurent994a6932013-07-17 11:51:42 -07009633 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009634 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009635
9636err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309637 if (in->usecase == USECASE_AUDIO_RECORD) {
9638 pthread_mutex_lock(&adev->lock);
9639 adev->pcm_record_uc_state = 0;
9640 pthread_mutex_unlock(&adev->lock);
9641 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009642 free(in);
9643 *stream_in = NULL;
9644 return ret;
9645}
9646
9647static void adev_close_input_stream(struct audio_hw_device *dev,
9648 struct audio_stream_in *stream)
9649{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009650 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009651 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009652 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309653
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309654 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009655
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009656 if (in == NULL) {
9657 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9658 return;
9659 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009660 io_streams_map_remove(adev, in->capture_handle);
9661
kunleiz70e57612018-12-28 17:50:23 +08009662 /* must deregister from sndmonitor first to prevent races
9663 * between the callback and close_stream
9664 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309665 audio_extn_snd_mon_unregister_listener(stream);
9666
kunleiz70e57612018-12-28 17:50:23 +08009667 /* Disable echo reference if there are no active input, hfp call
9668 * and sound trigger while closing input stream
9669 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009670 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009671 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009672 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9673 struct listnode out_devices;
9674 list_init(&out_devices);
9675 platform_set_echo_reference(adev, false, &out_devices);
9676 } else
kunleiz70e57612018-12-28 17:50:23 +08009677 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309678
Weiyin Jiang2995f662019-04-17 14:25:12 +08009679 error_log_destroy(in->error_log);
9680 in->error_log = NULL;
9681
Pallavid7c7a272018-01-16 11:22:55 +05309682
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009683 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309684 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009685 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309686 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009687 if (ret != 0)
9688 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9689 __func__, ret);
9690 } else
9691 in_standby(&stream->common);
9692
Revathi Uddarajud2634032017-12-07 14:42:34 +05309693 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309694 if (in->usecase == USECASE_AUDIO_RECORD) {
9695 adev->pcm_record_uc_state = 0;
9696 }
9697
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009698 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9699 adev->enable_voicerx = false;
9700 }
9701
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009702 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009703 audio_extn_ssr_deinit();
9704 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009705
Garmond Leunge2433c32017-09-28 21:51:22 -07009706 if (audio_extn_ffv_get_stream() == in) {
9707 audio_extn_ffv_stream_deinit();
9708 }
9709
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309710 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009711 audio_extn_compr_cap_format_supported(in->config.format))
9712 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309713
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309714 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309715 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009716
Mingming Yinfd7607b2016-01-22 12:48:44 -08009717 if (in->is_st_session) {
9718 ALOGV("%s: sound trigger pcm stop lab", __func__);
9719 audio_extn_sound_trigger_stop_lab(in);
9720 }
Derek Chenf939fb72018-11-13 13:34:41 -08009721 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9722 if (in_ctxt != NULL) {
9723 list_remove(&in_ctxt->list);
9724 free(in_ctxt);
9725 } else {
9726 ALOGW("%s, input stream already closed", __func__);
9727 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009728 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309729 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009730 return;
9731}
9732
Aalique Grahame22e49102018-12-18 14:23:57 -08009733/* verifies input and output devices and their capabilities.
9734 *
9735 * This verification is required when enabling extended bit-depth or
9736 * sampling rates, as not all qcom products support it.
9737 *
9738 * Suitable for calling only on initialization such as adev_open().
9739 * It fills the audio_device use_case_table[] array.
9740 *
9741 * Has a side-effect that it needs to configure audio routing / devices
9742 * in order to power up the devices and read the device parameters.
9743 * It does not acquire any hw device lock. Should restore the devices
9744 * back to "normal state" upon completion.
9745 */
9746static int adev_verify_devices(struct audio_device *adev)
9747{
9748 /* enumeration is a bit difficult because one really wants to pull
9749 * the use_case, device id, etc from the hidden pcm_device_table[].
9750 * In this case there are the following use cases and device ids.
9751 *
9752 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9753 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9754 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9755 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9756 * [USECASE_AUDIO_RECORD] = {0, 0},
9757 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9758 * [USECASE_VOICE_CALL] = {2, 2},
9759 *
9760 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9761 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9762 */
9763
9764 /* should be the usecases enabled in adev_open_input_stream() */
9765 static const int test_in_usecases[] = {
9766 USECASE_AUDIO_RECORD,
9767 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9768 };
9769 /* should be the usecases enabled in adev_open_output_stream()*/
9770 static const int test_out_usecases[] = {
9771 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9772 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9773 };
9774 static const usecase_type_t usecase_type_by_dir[] = {
9775 PCM_PLAYBACK,
9776 PCM_CAPTURE,
9777 };
9778 static const unsigned flags_by_dir[] = {
9779 PCM_OUT,
9780 PCM_IN,
9781 };
9782
9783 size_t i;
9784 unsigned dir;
9785 const unsigned card_id = adev->snd_card;
9786
9787 for (dir = 0; dir < 2; ++dir) {
9788 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9789 const unsigned flags_dir = flags_by_dir[dir];
9790 const size_t testsize =
9791 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9792 const int *testcases =
9793 dir ? test_in_usecases : test_out_usecases;
9794 const audio_devices_t audio_device =
9795 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9796
9797 for (i = 0; i < testsize; ++i) {
9798 const audio_usecase_t audio_usecase = testcases[i];
9799 int device_id;
9800 struct pcm_params **pparams;
9801 struct stream_out out;
9802 struct stream_in in;
9803 struct audio_usecase uc_info;
9804 int retval;
9805
9806 pparams = &adev->use_case_table[audio_usecase];
9807 pcm_params_free(*pparams); /* can accept null input */
9808 *pparams = NULL;
9809
9810 /* find the device ID for the use case (signed, for error) */
9811 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9812 if (device_id < 0)
9813 continue;
9814
9815 /* prepare structures for device probing */
9816 memset(&uc_info, 0, sizeof(uc_info));
9817 uc_info.id = audio_usecase;
9818 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009819 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009820 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009821 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009822 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009823 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009824 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9825 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009826 }
9827 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009828 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009829 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009830 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009831 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009832 uc_info.in_snd_device = SND_DEVICE_NONE;
9833 uc_info.out_snd_device = SND_DEVICE_NONE;
9834 list_add_tail(&adev->usecase_list, &uc_info.list);
9835
9836 /* select device - similar to start_(in/out)put_stream() */
9837 retval = select_devices(adev, audio_usecase);
9838 if (retval >= 0) {
9839 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9840#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009841 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009842 if (*pparams) {
9843 ALOGV("%s: (%s) card %d device %d", __func__,
9844 dir ? "input" : "output", card_id, device_id);
9845 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9846 } else {
9847 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9848 }
9849#endif
9850 }
9851
9852 /* deselect device - similar to stop_(in/out)put_stream() */
9853 /* 1. Get and set stream specific mixer controls */
9854 retval = disable_audio_route(adev, &uc_info);
9855 /* 2. Disable the rx device */
9856 retval = disable_snd_device(adev,
9857 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9858 list_remove(&uc_info.list);
9859 }
9860 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009861 return 0;
9862}
9863
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009864int update_patch(unsigned int num_sources,
9865 const struct audio_port_config *sources,
9866 unsigned int num_sinks,
9867 const struct audio_port_config *sinks,
9868 audio_patch_handle_t handle,
9869 struct audio_patch_info *p_info,
9870 patch_type_t patch_type, bool new_patch)
9871{
9872 ALOGD("%s: enter", __func__);
9873
9874 if (p_info == NULL) {
9875 ALOGE("%s: Invalid patch pointer", __func__);
9876 return -EINVAL;
9877 }
9878
9879 if (new_patch) {
9880 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9881 if (p_info->patch == NULL) {
9882 ALOGE("%s: Could not allocate patch", __func__);
9883 return -ENOMEM;
9884 }
9885 }
9886
9887 p_info->patch->id = handle;
9888 p_info->patch->num_sources = num_sources;
9889 p_info->patch->num_sinks = num_sinks;
9890
9891 for (int i = 0; i < num_sources; i++)
9892 p_info->patch->sources[i] = sources[i];
9893 for (int i = 0; i < num_sinks; i++)
9894 p_info->patch->sinks[i] = sinks[i];
9895
9896 p_info->patch_type = patch_type;
9897 return 0;
9898}
9899
9900audio_patch_handle_t generate_patch_handle()
9901{
9902 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9903 if (++patch_handle < 0)
9904 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9905 return patch_handle;
9906}
9907
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309908int adev_create_audio_patch(struct audio_hw_device *dev,
9909 unsigned int num_sources,
9910 const struct audio_port_config *sources,
9911 unsigned int num_sinks,
9912 const struct audio_port_config *sinks,
9913 audio_patch_handle_t *handle)
9914{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009915 int ret = 0;
9916 struct audio_device *adev = (struct audio_device *)dev;
9917 struct audio_patch_info *p_info = NULL;
9918 patch_type_t patch_type = PATCH_NONE;
9919 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9920 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9921 struct audio_stream_info *s_info = NULL;
9922 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009923 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009924 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9925 bool new_patch = false;
9926 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309927
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009928 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9929 num_sources, num_sinks, *handle);
9930
9931 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9932 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9933 ALOGE("%s: Invalid patch arguments", __func__);
9934 ret = -EINVAL;
9935 goto done;
9936 }
9937
9938 if (num_sources > 1) {
9939 ALOGE("%s: Multiple sources are not supported", __func__);
9940 ret = -EINVAL;
9941 goto done;
9942 }
9943
9944 if (sources == NULL || sinks == NULL) {
9945 ALOGE("%s: Invalid sources or sinks port config", __func__);
9946 ret = -EINVAL;
9947 goto done;
9948 }
9949
9950 ALOGV("%s: source role %d, source type %d", __func__,
9951 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009952 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009953
9954 // Populate source/sink information and fetch stream info
9955 switch (sources[0].type) {
9956 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9957 device_type = sources[0].ext.device.type;
9958 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009959 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009960 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9961 patch_type = PATCH_CAPTURE;
9962 io_handle = sinks[0].ext.mix.handle;
9963 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009964 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009965 __func__, device_type, io_handle);
9966 } else {
9967 // Device to device patch is not implemented.
9968 // This space will need changes if audio HAL
9969 // handles device to device patches in the future.
9970 patch_type = PATCH_DEVICE_LOOPBACK;
9971 }
9972 break;
9973 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9974 io_handle = sources[0].ext.mix.handle;
9975 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009976 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009977 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009978 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009979 }
9980 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009981 ALOGD("%s: Playback patch from mix handle %d to device %x",
9982 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009983 break;
9984 case AUDIO_PORT_TYPE_SESSION:
9985 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009986 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9987 ret = -EINVAL;
9988 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009989 }
9990
9991 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009992
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009993 // Generate patch info and update patch
9994 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009995 *handle = generate_patch_handle();
9996 p_info = (struct audio_patch_info *)
9997 calloc(1, sizeof(struct audio_patch_info));
9998 if (p_info == NULL) {
9999 ALOGE("%s: Failed to allocate memory", __func__);
10000 pthread_mutex_unlock(&adev->lock);
10001 ret = -ENOMEM;
10002 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010003 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010004 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010005 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010006 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010007 if (p_info == NULL) {
10008 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10009 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010010 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010011 ret = -EINVAL;
10012 goto done;
10013 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010014 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010015 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010016 *handle, p_info, patch_type, new_patch);
10017
10018 // Fetch stream info of associated mix for playback or capture patches
10019 if (p_info->patch_type == PATCH_PLAYBACK ||
10020 p_info->patch_type == PATCH_CAPTURE) {
10021 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10022 if (s_info == NULL) {
10023 ALOGE("%s: Failed to obtain stream info", __func__);
10024 if (new_patch)
10025 free(p_info);
10026 pthread_mutex_unlock(&adev->lock);
10027 ret = -EINVAL;
10028 goto done;
10029 }
10030 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10031 s_info->patch_handle = *handle;
10032 stream = s_info->stream;
10033 }
10034 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010035
10036 // Update routing for stream
10037 if (stream != NULL) {
10038 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010039 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010040 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010041 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010042 if (ret < 0) {
10043 pthread_mutex_lock(&adev->lock);
10044 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10045 if (new_patch)
10046 free(p_info);
10047 pthread_mutex_unlock(&adev->lock);
10048 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10049 goto done;
10050 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010051 }
10052
10053 // Add new patch to patch map
10054 if (!ret && new_patch) {
10055 pthread_mutex_lock(&adev->lock);
10056 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010057 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010058 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010059 }
10060
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010061done:
10062 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010063 num_sources,
10064 sources,
10065 num_sinks,
10066 sinks,
10067 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010068 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010069 num_sources,
10070 sources,
10071 num_sinks,
10072 sinks,
10073 handle);
10074 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010075}
10076
10077int adev_release_audio_patch(struct audio_hw_device *dev,
10078 audio_patch_handle_t handle)
10079{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010080 struct audio_device *adev = (struct audio_device *) dev;
10081 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010082 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010083 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010084
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010085 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10086 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10087 ret = -EINVAL;
10088 goto done;
10089 }
10090
10091 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010092 pthread_mutex_lock(&adev->lock);
10093 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010094 if (p_info == NULL) {
10095 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010096 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010097 ret = -EINVAL;
10098 goto done;
10099 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010100 struct audio_patch *patch = p_info->patch;
10101 if (patch == NULL) {
10102 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010103 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010104 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010105 goto done;
10106 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010107 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10108 switch (patch->sources[0].type) {
10109 case AUDIO_PORT_TYPE_MIX:
10110 io_handle = patch->sources[0].ext.mix.handle;
10111 break;
10112 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010113 if (p_info->patch_type == PATCH_CAPTURE)
10114 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010115 break;
10116 case AUDIO_PORT_TYPE_SESSION:
10117 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010118 pthread_mutex_unlock(&adev->lock);
10119 ret = -EINVAL;
10120 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010121 }
10122
10123 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010124 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010125 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010126 if (patch_type == PATCH_PLAYBACK ||
10127 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010128 struct audio_stream_info *s_info =
10129 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10130 if (s_info == NULL) {
10131 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10132 pthread_mutex_unlock(&adev->lock);
10133 goto done;
10134 }
10135 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10136 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010137 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010138 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010139
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010140 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010141 struct listnode devices;
10142 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010143 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010144 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010145 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010146 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010147 }
10148
10149 if (ret < 0)
10150 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10151
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152done:
10153 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10154 audio_extn_auto_hal_release_audio_patch(dev, handle);
10155
10156 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010157 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010158}
10159
10160int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10161{
Derek Chenf13dd492018-11-13 14:53:51 -080010162 int ret = 0;
10163
10164 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10165 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10166 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010167}
10168
10169int adev_set_audio_port_config(struct audio_hw_device *dev,
10170 const struct audio_port_config *config)
10171{
Derek Chenf13dd492018-11-13 14:53:51 -080010172 int ret = 0;
10173
10174 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10175 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10176 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010177}
10178
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010179static int adev_dump(const audio_hw_device_t *device __unused,
10180 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010181{
10182 return 0;
10183}
10184
10185static int adev_close(hw_device_t *device)
10186{
Aalique Grahame22e49102018-12-18 14:23:57 -080010187 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010188 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010189
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010190 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010191 return 0;
10192
10193 pthread_mutex_lock(&adev_init_lock);
10194
10195 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010196 if (audio_extn_spkr_prot_is_enabled())
10197 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010198 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010199 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010200 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010201 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010202 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010203 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010204 audio_extn_utils_release_streams_cfg_lists(
10205 &adev->streams_output_cfg_list,
10206 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010207 if (audio_extn_qap_is_enabled())
10208 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010209 if (audio_extn_qaf_is_enabled())
10210 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010211 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010212 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010213 free(adev->snd_dev_ref_cnt);
10214 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010215 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10216 pcm_params_free(adev->use_case_table[i]);
10217 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010218 if (adev->adm_deinit)
10219 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010220 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010221 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010222 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010223 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010224 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010225 if (adev->device_cfg_params) {
10226 free(adev->device_cfg_params);
10227 adev->device_cfg_params = NULL;
10228 }
Derek Chend2530072014-11-24 12:39:14 -080010229 if(adev->ext_hw_plugin)
10230 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010231 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010232 free_map(adev->patch_map);
10233 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010234 free(device);
10235 adev = NULL;
10236 }
10237 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010238 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010239 return 0;
10240}
10241
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010242/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10243 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10244 * just that it _might_ work.
10245 */
10246static int period_size_is_plausible_for_low_latency(int period_size)
10247{
10248 switch (period_size) {
10249 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010250 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010251 case 240:
10252 case 320:
10253 case 480:
10254 return 1;
10255 default:
10256 return 0;
10257 }
10258}
10259
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010260static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10261{
10262 bool is_snd_card_status = false;
10263 bool is_ext_device_status = false;
10264 char value[32];
10265 int card = -1;
10266 card_status_t status;
10267
10268 if (cookie != adev || !parms)
10269 return;
10270
10271 if (!parse_snd_card_status(parms, &card, &status)) {
10272 is_snd_card_status = true;
10273 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10274 is_ext_device_status = true;
10275 } else {
10276 // not a valid event
10277 return;
10278 }
10279
10280 pthread_mutex_lock(&adev->lock);
10281 if (card == adev->snd_card || is_ext_device_status) {
10282 if (is_snd_card_status && adev->card_status != status) {
10283 adev->card_status = status;
10284 platform_snd_card_update(adev->platform, status);
10285 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010286 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010287 if (status == CARD_STATUS_OFFLINE)
10288 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010289 } else if (is_ext_device_status) {
10290 platform_set_parameters(adev->platform, parms);
10291 }
10292 }
10293 pthread_mutex_unlock(&adev->lock);
10294 return;
10295}
10296
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010297/* out and adev lock held */
10298static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10299{
10300 struct audio_usecase *uc_info;
10301 float left_p;
10302 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010303 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010304
10305 uc_info = get_usecase_from_list(adev, out->usecase);
10306 if (uc_info == NULL) {
10307 ALOGE("%s: Could not find the usecase (%d) in the list",
10308 __func__, out->usecase);
10309 return -EINVAL;
10310 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010311 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010312
10313 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10314 out->usecase, use_case_table[out->usecase]);
10315
10316 if (restore) {
10317 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010318 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010319 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010320 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10321 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010322 pthread_mutex_lock(&out->compr_mute_lock);
10323 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010324 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010325 out->a2dp_compress_mute = false;
10326 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10327 }
10328 pthread_mutex_unlock(&out->compr_mute_lock);
10329 }
10330 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010331 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10332 // mute compress stream if suspended
10333 pthread_mutex_lock(&out->compr_mute_lock);
10334 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010335 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010336 assign_devices(&devices, &out->device_list);
10337 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010338 left_p = out->volume_l;
10339 right_p = out->volume_r;
10340 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10341 compress_pause(out->compr);
10342 out_set_compr_volume(&out->stream, (float)0, (float)0);
10343 out->a2dp_compress_mute = true;
10344 select_devices(adev, out->usecase);
10345 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10346 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010347 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010348 out->volume_l = left_p;
10349 out->volume_r = right_p;
10350 }
Zhou Songc576a452019-09-09 14:17:40 +080010351 pthread_mutex_unlock(&out->compr_mute_lock);
10352 } else {
10353 // tear down a2dp path for non offloaded streams
10354 if (audio_extn_a2dp_source_is_suspended())
10355 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010356 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010357 }
10358 ALOGV("%s: exit", __func__);
10359 return 0;
10360}
10361
10362int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10363{
10364 int ret = 0;
10365
10366 lock_output_stream(out);
10367 pthread_mutex_lock(&adev->lock);
10368
10369 ret = check_a2dp_restore_l(adev, out, restore);
10370
10371 pthread_mutex_unlock(&adev->lock);
10372 pthread_mutex_unlock(&out->lock);
10373 return ret;
10374}
10375
Haynes Mathew George01156f92018-04-13 15:29:54 -070010376void adev_on_battery_status_changed(bool charging)
10377{
10378 pthread_mutex_lock(&adev->lock);
10379 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10380 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010381 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010382 pthread_mutex_unlock(&adev->lock);
10383}
10384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010385static int adev_open(const hw_module_t *module, const char *name,
10386 hw_device_t **device)
10387{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010388 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010389 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010390 char mixer_ctl_name[128] = {0};
10391 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010392
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010393 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010394 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10395
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010396 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010397 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010398 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010399 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010400 ALOGD("%s: returning existing instance of adev", __func__);
10401 ALOGD("%s: exit", __func__);
10402 pthread_mutex_unlock(&adev_init_lock);
10403 return 0;
10404 }
10405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010406 adev = calloc(1, sizeof(struct audio_device));
10407
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010408 if (!adev) {
10409 pthread_mutex_unlock(&adev_init_lock);
10410 return -ENOMEM;
10411 }
10412
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010413 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10414
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010415 // register audio ext hidl at the earliest
10416 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010417#ifdef DYNAMIC_LOG_ENABLED
10418 register_for_dynamic_logging("hal");
10419#endif
10420
Derek Chenf939fb72018-11-13 13:34:41 -080010421 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010422 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010423 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10424 maj_version = atoi(value);
10425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010426 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010427 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010428 adev->device.common.module = (struct hw_module_t *)module;
10429 adev->device.common.close = adev_close;
10430
10431 adev->device.init_check = adev_init_check;
10432 adev->device.set_voice_volume = adev_set_voice_volume;
10433 adev->device.set_master_volume = adev_set_master_volume;
10434 adev->device.get_master_volume = adev_get_master_volume;
10435 adev->device.set_master_mute = adev_set_master_mute;
10436 adev->device.get_master_mute = adev_get_master_mute;
10437 adev->device.set_mode = adev_set_mode;
10438 adev->device.set_mic_mute = adev_set_mic_mute;
10439 adev->device.get_mic_mute = adev_get_mic_mute;
10440 adev->device.set_parameters = adev_set_parameters;
10441 adev->device.get_parameters = adev_get_parameters;
10442 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10443 adev->device.open_output_stream = adev_open_output_stream;
10444 adev->device.close_output_stream = adev_close_output_stream;
10445 adev->device.open_input_stream = adev_open_input_stream;
10446 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010447 adev->device.create_audio_patch = adev_create_audio_patch;
10448 adev->device.release_audio_patch = adev_release_audio_patch;
10449 adev->device.get_audio_port = adev_get_audio_port;
10450 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010451 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010452 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010453
10454 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010455 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010456 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010457 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010458 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010459 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010460 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010461 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010462 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010463 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010464 /* Init audio and voice feature */
10465 audio_extn_feature_init();
10466 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010467 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010468 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010469 list_init(&adev->active_inputs_list);
10470 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010471 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010472 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10473 audio_extn_utils_hash_eq);
10474 if (!adev->io_streams_map) {
10475 ALOGE("%s: Could not create io streams map", __func__);
10476 ret = -ENOMEM;
10477 goto adev_open_err;
10478 }
10479 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10480 audio_extn_utils_hash_eq);
10481 if (!adev->patch_map) {
10482 ALOGE("%s: Could not create audio patch map", __func__);
10483 ret = -ENOMEM;
10484 goto adev_open_err;
10485 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010486 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010487 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010488 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010489 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010490 adev->perf_lock_opts[0] = 0x101;
10491 adev->perf_lock_opts[1] = 0x20E;
10492 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010493 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010494 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010495 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010496 adev->adm_routing_changed = false;
Revathi Uddarajub26e3932020-06-10 14:51:02 +053010497 adev->a2dp_started = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010498
Zhou Song68ebc352019-12-05 17:11:15 +080010499 audio_extn_perf_lock_init();
10500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010501 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010502 adev->platform = platform_init(adev);
10503 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010504 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010505 ret = -EINVAL;
10506 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010507 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010508
Aalique Grahame22e49102018-12-18 14:23:57 -080010509 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010510 if (audio_extn_qap_is_enabled()) {
10511 ret = audio_extn_qap_init(adev);
10512 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010513 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010514 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010515 }
10516 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10517 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10518 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010519
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010520 if (audio_extn_qaf_is_enabled()) {
10521 ret = audio_extn_qaf_init(adev);
10522 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010523 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010524 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010525 }
10526
10527 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10528 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10529 }
10530
Derek Chenae7b0342019-02-08 15:17:04 -080010531 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010532 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10533
Eric Laurentc4aef752013-09-12 17:45:53 -070010534 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10535 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10536 if (adev->visualizer_lib == NULL) {
10537 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10538 } else {
10539 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10540 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010541 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010542 "visualizer_hal_start_output");
10543 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010544 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010545 "visualizer_hal_stop_output");
10546 }
10547 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010548 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010549 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010550 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010551 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010552 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010553 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010554
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010555 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10556 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10557 if (adev->offload_effects_lib == NULL) {
10558 ALOGE("%s: DLOPEN failed for %s", __func__,
10559 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10560 } else {
10561 ALOGV("%s: DLOPEN successful for %s", __func__,
10562 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10563 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010564 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010565 "offload_effects_bundle_hal_start_output");
10566 adev->offload_effects_stop_output =
10567 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10568 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010569 adev->offload_effects_set_hpx_state =
10570 (int (*)(bool))dlsym(adev->offload_effects_lib,
10571 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010572 adev->offload_effects_get_parameters =
10573 (void (*)(struct str_parms *, struct str_parms *))
10574 dlsym(adev->offload_effects_lib,
10575 "offload_effects_bundle_get_parameters");
10576 adev->offload_effects_set_parameters =
10577 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10578 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010579 }
10580 }
10581
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010582 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10583 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10584 if (adev->adm_lib == NULL) {
10585 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10586 } else {
10587 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10588 adev->adm_init = (adm_init_t)
10589 dlsym(adev->adm_lib, "adm_init");
10590 adev->adm_deinit = (adm_deinit_t)
10591 dlsym(adev->adm_lib, "adm_deinit");
10592 adev->adm_register_input_stream = (adm_register_input_stream_t)
10593 dlsym(adev->adm_lib, "adm_register_input_stream");
10594 adev->adm_register_output_stream = (adm_register_output_stream_t)
10595 dlsym(adev->adm_lib, "adm_register_output_stream");
10596 adev->adm_deregister_stream = (adm_deregister_stream_t)
10597 dlsym(adev->adm_lib, "adm_deregister_stream");
10598 adev->adm_request_focus = (adm_request_focus_t)
10599 dlsym(adev->adm_lib, "adm_request_focus");
10600 adev->adm_abandon_focus = (adm_abandon_focus_t)
10601 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010602 adev->adm_set_config = (adm_set_config_t)
10603 dlsym(adev->adm_lib, "adm_set_config");
10604 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10605 dlsym(adev->adm_lib, "adm_request_focus_v2");
10606 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10607 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10608 adev->adm_on_routing_change = (adm_on_routing_change_t)
10609 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010610 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10611 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010612 }
10613 }
10614
Aalique Grahame22e49102018-12-18 14:23:57 -080010615 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010616 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010617 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010618 //initialize this to false for now,
10619 //this will be set to true through set param
10620 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010621
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010622 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010623 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010624
10625 if (k_enable_extended_precision)
10626 adev_verify_devices(adev);
10627
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010628 adev->dsp_bit_width_enforce_mode =
10629 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010630
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010631 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10632 &adev->streams_output_cfg_list,
10633 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010634
Kiran Kandi910e1862013-10-29 13:29:42 -070010635 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010636
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010637 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010638 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010639 trial = atoi(value);
10640 if (period_size_is_plausible_for_low_latency(trial)) {
10641 pcm_config_low_latency.period_size = trial;
10642 pcm_config_low_latency.start_threshold = trial / 4;
10643 pcm_config_low_latency.avail_min = trial / 4;
10644 configured_low_latency_capture_period_size = trial;
10645 }
10646 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010647 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10648 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010649 trial = atoi(value);
10650 if (period_size_is_plausible_for_low_latency(trial)) {
10651 configured_low_latency_capture_period_size = trial;
10652 }
10653 }
10654
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010655 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10656
Eric Laurent4b084132018-10-19 17:33:43 -070010657 adev->camera_orientation = CAMERA_DEFAULT;
10658
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010659 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010660 af_period_multiplier = atoi(value);
10661 if (af_period_multiplier < 0)
10662 af_period_multiplier = 2;
10663 else if (af_period_multiplier > 4)
10664 af_period_multiplier = 4;
10665
10666 ALOGV("new period_multiplier = %d", af_period_multiplier);
10667 }
10668
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010669 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010670
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010671 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010672 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010673 pthread_mutex_unlock(&adev_init_lock);
10674
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010675 if (adev->adm_init)
10676 adev->adm_data = adev->adm_init();
10677
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010678 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010679 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010680
10681 audio_extn_snd_mon_init();
10682 pthread_mutex_lock(&adev->lock);
10683 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10684 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010685 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10686 /*
10687 * if the battery state callback happens before charging can be queried,
10688 * it will be guarded with the adev->lock held in the cb function and so
10689 * the callback value will reflect the latest state
10690 */
10691 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010692 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010693 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010694 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010695 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010696 /* Allocate memory for Device config params */
10697 adev->device_cfg_params = (struct audio_device_config_param*)
10698 calloc(platform_get_max_codec_backend(),
10699 sizeof(struct audio_device_config_param));
10700 if (adev->device_cfg_params == NULL)
10701 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010702
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010703 /*
10704 * Check if new PSPD matrix mixer control is supported. If not
10705 * supported, then set flag so that old mixer ctrl is sent while
10706 * sending pspd coefficients on older kernel version. Query mixer
10707 * control for default pcm id and channel value one.
10708 */
10709 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10710 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10711
10712 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10713 if (!ctl) {
10714 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10715 __func__, mixer_ctl_name);
10716 adev->use_old_pspd_mix_ctrl = true;
10717 }
10718
Eric Laurent994a6932013-07-17 11:51:42 -070010719 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010720 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010721
10722adev_open_err:
10723 free_map(adev->patch_map);
10724 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010725 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010726 pthread_mutex_destroy(&adev->lock);
10727 free(adev);
10728 adev = NULL;
10729 *device = NULL;
10730 pthread_mutex_unlock(&adev_init_lock);
10731 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010732}
10733
10734static struct hw_module_methods_t hal_module_methods = {
10735 .open = adev_open,
10736};
10737
10738struct audio_module HAL_MODULE_INFO_SYM = {
10739 .common = {
10740 .tag = HARDWARE_MODULE_TAG,
10741 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10742 .hal_api_version = HARDWARE_HAL_API_VERSION,
10743 .id = AUDIO_HARDWARE_MODULE_ID,
10744 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010745 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010746 .methods = &hal_module_methods,
10747 },
10748};