blob: 82a5d927003da69f2977590acbd545abf972535a [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;
Andy Hung756ecc12018-10-19 17:47:12 -07001294 // we shouldn't truncate mixer_path
1295 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1296 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1297 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001298 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001299 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001300 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001301 if (usecase->type == PCM_CAPTURE) {
1302 struct stream_in *in = usecase->stream.in;
1303 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001304 struct listnode out_devices;
1305 list_init(&out_devices);
1306 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001307 in->ec_opened = false;
1308 }
1309 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001310 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301311 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301312
1313 if (usecase->type == PCM_CAPTURE) {
1314 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001315 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301316 ALOGD("%s: reset custom mtmx params v1", __func__);
1317 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1318 }
1319 } else {
1320 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1321 }
1322
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001323 if ((usecase->type == PCM_PLAYBACK) &&
1324 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301325 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301326
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001327 ALOGV("%s: exit", __func__);
1328 return 0;
1329}
1330
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001331int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001332 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001333{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301334 int i, num_devices = 0;
1335 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001336 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1337
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001338 if (snd_device < SND_DEVICE_MIN ||
1339 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001340 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001341 return -EINVAL;
1342 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001343
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001344 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001345 ALOGE("%s: Invalid sound device returned", __func__);
1346 return -EINVAL;
1347 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001348
1349 adev->snd_dev_ref_cnt[snd_device]++;
1350
1351 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1352 (platform_split_snd_device(adev->platform,
1353 snd_device,
1354 &num_devices,
1355 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001356 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001357 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001358 return 0;
1359 }
1360
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001361 if (audio_extn_spkr_prot_is_enabled())
1362 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001363
Aalique Grahame22e49102018-12-18 14:23:57 -08001364 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1365
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001366 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1367 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001368 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1369 goto err;
1370 }
1371 audio_extn_dev_arbi_acquire(snd_device);
1372 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001373 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001374 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001375 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001376 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001377 } else if (platform_split_snd_device(adev->platform,
1378 snd_device,
1379 &num_devices,
1380 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301381 for (i = 0; i < num_devices; i++) {
1382 enable_snd_device(adev, new_snd_devices[i]);
1383 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001384 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001385 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001386 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301387
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301388
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001389 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1390 (audio_extn_a2dp_start_playback() < 0)) {
1391 ALOGE(" fail to configure A2dp Source control path ");
1392 goto err;
1393 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001394
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001395 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1396 (audio_extn_a2dp_start_capture() < 0)) {
1397 ALOGE(" fail to configure A2dp Sink control path ");
1398 goto err;
1399 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301400
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001401 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1402 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1403 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1404 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1405 ALOGE(" fail to configure sco control path ");
1406 goto err;
1407 }
Zhou Song12c29502019-03-16 10:37:18 +08001408 }
1409
Zhou Song331c8e52019-08-26 14:16:12 +08001410 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001411 /* due to the possibility of calibration overwrite between listen
1412 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001413 audio_extn_sound_trigger_update_device_status(snd_device,
1414 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301415 audio_extn_listen_update_device_status(snd_device,
1416 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001417 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001418 audio_extn_sound_trigger_update_device_status(snd_device,
1419 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301420 audio_extn_listen_update_device_status(snd_device,
1421 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001422 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001423 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001424 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001425 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301426
1427 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1428 !adev->native_playback_enabled &&
1429 audio_is_true_native_stream_active(adev)) {
1430 ALOGD("%s: %d: napb: enabling native mode in hardware",
1431 __func__, __LINE__);
1432 audio_route_apply_and_update_path(adev->audio_route,
1433 "true-native-mode");
1434 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301435 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301436 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1437 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001438 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001439 ALOGD("%s: init ec ref loopback", __func__);
1440 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1441 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001444err:
1445 adev->snd_dev_ref_cnt[snd_device]--;
1446 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001447}
1448
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001449int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001450 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301452 int i, num_devices = 0;
1453 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001454 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1455
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001456 if (snd_device < SND_DEVICE_MIN ||
1457 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001458 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001459 return -EINVAL;
1460 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001461
1462 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1463 ALOGE("%s: Invalid sound device returned", __func__);
1464 return -EINVAL;
1465 }
1466
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1468 ALOGE("%s: device ref cnt is already 0", __func__);
1469 return -EINVAL;
1470 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001471
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001472 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001473
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001474
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001476 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301477
Aalique Grahame22e49102018-12-18 14:23:57 -08001478 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1479
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001480 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1481 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001482 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001483
1484 // when speaker device is disabled, reset swap.
1485 // will be renabled on usecase start
1486 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001487 } else if (platform_split_snd_device(adev->platform,
1488 snd_device,
1489 &num_devices,
1490 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301491 for (i = 0; i < num_devices; i++) {
1492 disable_snd_device(adev, new_snd_devices[i]);
1493 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001494 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001495 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001496 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001497 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001498
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001499 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301500 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001501 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001502 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001503 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001504 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301505 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001506 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301507 adev->native_playback_enabled) {
1508 ALOGD("%s: %d: napb: disabling native mode in hardware",
1509 __func__, __LINE__);
1510 audio_route_reset_and_update_path(adev->audio_route,
1511 "true-native-mode");
1512 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001513 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301514 adev->asrc_mode_enabled) {
1515 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301516 disable_asrc_mode(adev);
1517 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001518 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301519 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001520 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001521 ALOGD("%s: deinit ec ref loopback", __func__);
1522 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1523 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001524
1525 audio_extn_utils_release_snd_device(snd_device);
1526 } else {
1527 if (platform_split_snd_device(adev->platform,
1528 snd_device,
1529 &num_devices,
1530 new_snd_devices) == 0) {
1531 for (i = 0; i < num_devices; i++) {
1532 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1533 }
1534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001536
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537 return 0;
1538}
1539
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001540/*
1541 legend:
1542 uc - existing usecase
1543 new_uc - new usecase
1544 d1, d11, d2 - SND_DEVICE enums
1545 a1, a2 - corresponding ANDROID device enums
1546 B1, B2 - backend strings
1547
1548case 1
1549 uc->dev d1 (a1) B1
1550 new_uc->dev d1 (a1), d2 (a2) B1, B2
1551
1552 resolution: disable and enable uc->dev on d1
1553
1554case 2
1555 uc->dev d1 (a1) B1
1556 new_uc->dev d11 (a1) B1
1557
1558 resolution: need to switch uc since d1 and d11 are related
1559 (e.g. speaker and voice-speaker)
1560 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1561
1562case 3
1563 uc->dev d1 (a1) B1
1564 new_uc->dev d2 (a2) B2
1565
1566 resolution: no need to switch uc
1567
1568case 4
1569 uc->dev d1 (a1) B1
1570 new_uc->dev d2 (a2) B1
1571
1572 resolution: disable enable uc-dev on d2 since backends match
1573 we cannot enable two streams on two different devices if they
1574 share the same backend. e.g. if offload is on speaker device using
1575 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1576 using the same backend, offload must also be switched to voice-handset.
1577
1578case 5
1579 uc->dev d1 (a1) B1
1580 new_uc->dev d1 (a1), d2 (a2) B1
1581
1582 resolution: disable enable uc-dev on d2 since backends match
1583 we cannot enable two streams on two different devices if they
1584 share the same backend.
1585
1586case 6
1587 uc->dev d1 (a1) B1
1588 new_uc->dev d2 (a1) B2
1589
1590 resolution: no need to switch
1591
1592case 7
1593 uc->dev d1 (a1), d2 (a2) B1, B2
1594 new_uc->dev d1 (a1) B1
1595
1596 resolution: no need to switch
1597
Zhou Song4ba65882018-07-09 14:48:07 +08001598case 8
1599 uc->dev d1 (a1) B1
1600 new_uc->dev d11 (a1), d2 (a2) B1, B2
1601 resolution: compared to case 1, for this case, d1 and d11 are related
1602 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001603*/
1604static snd_device_t derive_playback_snd_device(void * platform,
1605 struct audio_usecase *uc,
1606 struct audio_usecase *new_uc,
1607 snd_device_t new_snd_device)
1608{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001609 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001610
1611 snd_device_t d1 = uc->out_snd_device;
1612 snd_device_t d2 = new_snd_device;
1613
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001614 list_init(&a1);
1615 list_init(&a2);
1616
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301617 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301618 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001619 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1620 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301621 break;
1622 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001623 assign_devices(&a1, &uc->stream.out->device_list);
1624 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301625 break;
1626 }
1627
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001628 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001629 if (!compare_devices(&a1, &a2) &&
1630 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001631 snd_device_t d3[2];
1632 int num_devices = 0;
1633 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001634 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001635 &num_devices,
1636 d3);
1637 if (ret < 0) {
1638 if (ret != -ENOSYS) {
1639 ALOGW("%s failed to split snd_device %d",
1640 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001641 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001642 }
1643 goto end;
1644 }
1645
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001646 if (platform_check_backends_match(d3[0], d3[1])) {
1647 return d2; // case 5
1648 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001649 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301650 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001651 // check if d1 is related to any of d3's
1652 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001653 return d1; // case 1
1654 else
1655 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001656 }
1657 } else {
1658 if (platform_check_backends_match(d1, d2)) {
1659 return d2; // case 2, 4
1660 } else {
1661 return d1; // case 6, 3
1662 }
1663 }
1664
1665end:
1666 return d2; // return whatever was calculated before.
1667}
1668
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001669static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301670 struct audio_usecase *uc_info,
1671 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001672{
1673 struct listnode *node;
1674 struct audio_usecase *usecase;
1675 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301676 snd_device_t uc_derive_snd_device;
1677 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001678 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1679 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001680 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301681 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001682 /*
1683 * This function is to make sure that all the usecases that are active on
1684 * the hardware codec backend are always routed to any one device that is
1685 * handled by the hardware codec.
1686 * For example, if low-latency and deep-buffer usecases are currently active
1687 * on speaker and out_set_parameters(headset) is received on low-latency
1688 * output, then we have to make sure deep-buffer is also switched to headset,
1689 * because of the limitation that both the devices cannot be enabled
1690 * at the same time as they share the same backend.
1691 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001692 /*
1693 * This call is to check if we need to force routing for a particular stream
1694 * If there is a backend configuration change for the device when a
1695 * new stream starts, then ADM needs to be closed and re-opened with the new
1696 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001697 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001698 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001699 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1700 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301701 /* For a2dp device reconfigure all active sessions
1702 * with new AFE encoder format based on a2dp state
1703 */
1704 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1705 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1706 audio_extn_a2dp_is_force_device_switch()) {
1707 force_routing = true;
1708 force_restart_session = true;
1709 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301710 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1711
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001713 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001714 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001715 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1716 switch_device[i] = false;
1717
1718 list_for_each(node, &adev->usecase_list) {
1719 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001720
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301721 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1722 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301723 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301724 platform_get_snd_device_name(usecase->out_snd_device),
1725 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301726 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1727 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301728 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1729 usecase, uc_info, snd_device);
1730 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001731 (is_codec_backend_out_device_type(&usecase->device_list) ||
1732 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1733 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1734 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1735 is_a2dp_out_device_type(&usecase->device_list) ||
1736 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301737 ((force_restart_session) ||
1738 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301739 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1740 __func__, use_case_table[usecase->id],
1741 platform_get_snd_device_name(usecase->out_snd_device));
1742 disable_audio_route(adev, usecase);
1743 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301744 /* Enable existing usecase on derived playback device */
1745 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301746 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301747 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001748 }
1749 }
1750
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301751 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1752 num_uc_to_switch);
1753
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001754 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001755 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001756
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301757 /* Make sure the previous devices to be disabled first and then enable the
1758 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001759 list_for_each(node, &adev->usecase_list) {
1760 usecase = node_to_item(node, struct audio_usecase, list);
1761 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001762 /* Check if output sound device to be switched can be split and if any
1763 of the split devices match with derived sound device */
1764 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1765 &num_devices, split_snd_devices) == 0) {
1766 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1767 for (i = 0; i < num_devices; i++) {
1768 /* Disable devices that do not match with derived sound device */
1769 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1770 disable_snd_device(adev, split_snd_devices[i]);
1771 }
1772 } else {
1773 disable_snd_device(adev, usecase->out_snd_device);
1774 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001775 }
1776 }
1777
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001778 list_for_each(node, &adev->usecase_list) {
1779 usecase = node_to_item(node, struct audio_usecase, list);
1780 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001781 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1782 &num_devices, split_snd_devices) == 0) {
1783 /* Enable derived sound device only if it does not match with
1784 one of the split sound devices. This is because the matching
1785 sound device was not disabled */
1786 bool should_enable = true;
1787 for (i = 0; i < num_devices; i++) {
1788 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1789 should_enable = false;
1790 break;
1791 }
1792 }
1793 if (should_enable)
1794 enable_snd_device(adev, derive_snd_device[usecase->id]);
1795 } else {
1796 enable_snd_device(adev, derive_snd_device[usecase->id]);
1797 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001798 }
1799 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001800
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001801 /* Re-route all the usecases on the shared backend other than the
1802 specified usecase to new snd devices */
1803 list_for_each(node, &adev->usecase_list) {
1804 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301805 /* Update the out_snd_device only before enabling the audio route */
1806 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301807 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301808 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301809 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301810 use_case_table[usecase->id],
1811 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001812 /* Update voc calibration before enabling VoIP route */
1813 if (usecase->type == VOIP_CALL)
1814 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001815 usecase->out_snd_device,
1816 platform_get_input_snd_device(
1817 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301818 &uc_info->device_list,
1819 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301820 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301821 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001822 out_set_voip_volume(&usecase->stream.out->stream,
1823 usecase->stream.out->volume_l,
1824 usecase->stream.out->volume_r);
1825 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301826 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001827 }
1828 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001829 }
1830}
1831
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301832static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001833 struct audio_usecase *uc_info,
1834 snd_device_t snd_device)
1835{
1836 struct listnode *node;
1837 struct audio_usecase *usecase;
1838 bool switch_device[AUDIO_USECASE_MAX];
1839 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001840 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001841 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001842
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301843 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1844 snd_device);
1845 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301846
1847 /*
1848 * Make sure out devices is checked against out codec backend device and
1849 * also in devices against in codec backend. Checking out device against in
1850 * codec backend or vice versa causes issues.
1851 */
1852 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001853 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001854 /*
1855 * This function is to make sure that all the active capture usecases
1856 * are always routed to the same input sound device.
1857 * For example, if audio-record and voice-call usecases are currently
1858 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1859 * is received for voice call then we have to make sure that audio-record
1860 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1861 * because of the limitation that two devices cannot be enabled
1862 * at the same time if they share the same backend.
1863 */
1864 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1865 switch_device[i] = false;
1866
1867 list_for_each(node, &adev->usecase_list) {
1868 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301869 /*
1870 * TODO: Enhance below condition to handle BT sco/USB multi recording
1871 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301872
1873 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1874 (usecase->in_snd_device != snd_device || force_routing));
1875 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1876 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1877 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001878 ((backend_check_cond &&
1879 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001880 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001881 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001882 is_single_device_type_equal(&usecase->device_list,
1883 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001884 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001885 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001886 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301887 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001888 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001889 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001890 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001891 switch_device[usecase->id] = true;
1892 num_uc_to_switch++;
1893 }
1894 }
1895
1896 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001897 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001898
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301899 /* Make sure the previous devices to be disabled first and then enable the
1900 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001901 list_for_each(node, &adev->usecase_list) {
1902 usecase = node_to_item(node, struct audio_usecase, list);
1903 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001904 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001905 }
1906 }
1907
1908 list_for_each(node, &adev->usecase_list) {
1909 usecase = node_to_item(node, struct audio_usecase, list);
1910 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001911 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001912 }
1913 }
1914
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001915 /* Re-route all the usecases on the shared backend other than the
1916 specified usecase to new snd devices */
1917 list_for_each(node, &adev->usecase_list) {
1918 usecase = node_to_item(node, struct audio_usecase, list);
1919 /* Update the in_snd_device only before enabling the audio route */
1920 if (switch_device[usecase->id] ) {
1921 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001922 if (usecase->type != VOICE_CALL) {
1923 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301924 if (usecase->type == VOIP_CALL) {
1925 snd_device_t voip_snd_device;
1926 voip_snd_device = platform_get_output_snd_device(adev->platform,
1927 uc_info->stream.out,
1928 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08001929 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301930 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08001931 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05301932 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05301933 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001934 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001935 }
1936 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001937 }
1938}
1939
Mingming Yin3a941d42016-02-17 18:08:05 -08001940static void reset_hdmi_sink_caps(struct stream_out *out) {
1941 int i = 0;
1942
1943 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1944 out->supported_channel_masks[i] = 0;
1945 }
1946 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1947 out->supported_formats[i] = 0;
1948 }
1949 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1950 out->supported_sample_rates[i] = 0;
1951 }
1952}
1953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001955static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956{
Mingming Yin3a941d42016-02-17 18:08:05 -08001957 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001958 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
1959 out->extconn.cs.controller,
1960 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961
Mingming Yin3a941d42016-02-17 18:08:05 -08001962 reset_hdmi_sink_caps(out);
1963
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001964 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08001965 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001966 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08001967 out->extconn.cs.stream);
1968 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001969 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001970 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001971 }
1972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001975 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001976 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001977 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1978 case 6:
1979 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1980 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1981 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1982 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1983 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1984 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001985 break;
1986 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001987 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001988 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 break;
1990 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001991
1992 // check channel format caps
1993 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001994 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
1995 out->extconn.cs.controller,
1996 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08001997 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1998 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1999 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2000 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2001 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2002 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2003 }
2004
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002005 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2006 out->extconn.cs.controller,
2007 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002008 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2009 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2010 }
2011
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002012 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2013 out->extconn.cs.controller,
2014 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002015 ALOGV(":%s HDMI supports DTS format", __func__);
2016 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2017 }
2018
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002019 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2020 out->extconn.cs.controller,
2021 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002022 ALOGV(":%s HDMI supports DTS HD format", __func__);
2023 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2024 }
2025
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002026 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2027 out->extconn.cs.controller,
2028 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002029 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2030 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2031 }
2032
Mingming Yin3a941d42016-02-17 18:08:05 -08002033
2034 // check sample rate caps
2035 i = 0;
2036 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002037 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2038 out->extconn.cs.controller,
2039 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002040 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2041 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2042 }
2043 }
2044
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002045 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046}
2047
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002048static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2049 uint32_t *supported_sample_rates __unused,
2050 uint32_t max_rates __unused)
2051{
2052 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2053 supported_sample_rates,
2054 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302055 ssize_t i = 0;
2056
2057 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002058 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2059 supported_sample_rates[i]);
2060 }
2061 return count;
2062}
2063
2064static inline int read_usb_sup_channel_masks(bool is_playback,
2065 audio_channel_mask_t *supported_channel_masks,
2066 uint32_t max_masks)
2067{
2068 int channels = audio_extn_usb_get_max_channels(is_playback);
2069 int channel_count;
2070 uint32_t num_masks = 0;
2071 if (channels > MAX_HIFI_CHANNEL_COUNT)
2072 channels = MAX_HIFI_CHANNEL_COUNT;
2073
2074 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002075 // start from 2 channels as framework currently doesn't support mono.
2076 if (channels >= FCC_2) {
2077 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2078 }
2079 for (channel_count = FCC_2;
2080 channel_count <= channels && num_masks < max_masks;
2081 ++channel_count) {
2082 supported_channel_masks[num_masks++] =
2083 audio_channel_mask_for_index_assignment_from_count(channel_count);
2084 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002085 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002086 // For capture we report all supported channel masks from 1 channel up.
2087 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002088 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2089 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002090 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2091 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2092 if (channel_count <= FCC_2) {
2093 mask = audio_channel_in_mask_from_count(channel_count);
2094 supported_channel_masks[num_masks++] = mask;
2095 }
2096 const audio_channel_mask_t index_mask =
2097 audio_channel_mask_for_index_assignment_from_count(channel_count);
2098 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2099 supported_channel_masks[num_masks++] = index_mask;
2100 }
2101 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002102 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302103
vincenttewf51c94e2019-05-07 10:28:53 +08002104 for (size_t i = 0; i < num_masks; ++i) {
2105 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2106 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302107 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002108 return num_masks;
2109}
2110
2111static inline int read_usb_sup_formats(bool is_playback __unused,
2112 audio_format_t *supported_formats,
2113 uint32_t max_formats __unused)
2114{
2115 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2116 switch (bitwidth) {
2117 case 24:
2118 // XXX : usb.c returns 24 for s24 and s24_le?
2119 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2120 break;
2121 case 32:
2122 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2123 break;
2124 case 16:
2125 default :
2126 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2127 break;
2128 }
2129 ALOGV("%s: %s supported format %d", __func__,
2130 is_playback ? "P" : "C", bitwidth);
2131 return 1;
2132}
2133
2134static inline int read_usb_sup_params_and_compare(bool is_playback,
2135 audio_format_t *format,
2136 audio_format_t *supported_formats,
2137 uint32_t max_formats,
2138 audio_channel_mask_t *mask,
2139 audio_channel_mask_t *supported_channel_masks,
2140 uint32_t max_masks,
2141 uint32_t *rate,
2142 uint32_t *supported_sample_rates,
2143 uint32_t max_rates) {
2144 int ret = 0;
2145 int num_formats;
2146 int num_masks;
2147 int num_rates;
2148 int i;
2149
2150 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2151 max_formats);
2152 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2153 max_masks);
2154
2155 num_rates = read_usb_sup_sample_rates(is_playback,
2156 supported_sample_rates, max_rates);
2157
2158#define LUT(table, len, what, dflt) \
2159 for (i=0; i<len && (table[i] != what); i++); \
2160 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2161
2162 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2163 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2164 LUT(supported_sample_rates, num_rates, *rate, 0);
2165
2166#undef LUT
2167 return ret < 0 ? -EINVAL : 0; // HACK TBD
2168}
2169
Alexy Josephb1379942016-01-29 15:49:38 -08002170audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002171 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002172{
2173 struct audio_usecase *usecase;
2174 struct listnode *node;
2175
2176 list_for_each(node, &adev->usecase_list) {
2177 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002178 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002179 ALOGV("%s: usecase id %d", __func__, usecase->id);
2180 return usecase->id;
2181 }
2182 }
2183 return USECASE_INVALID;
2184}
2185
Alexy Josephb1379942016-01-29 15:49:38 -08002186struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002187 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002188{
2189 struct audio_usecase *usecase;
2190 struct listnode *node;
2191
2192 list_for_each(node, &adev->usecase_list) {
2193 usecase = node_to_item(node, struct audio_usecase, list);
2194 if (usecase->id == uc_id)
2195 return usecase;
2196 }
2197 return NULL;
2198}
2199
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302200/*
2201 * is a true native playback active
2202 */
2203bool audio_is_true_native_stream_active(struct audio_device *adev)
2204{
2205 bool active = false;
2206 int i = 0;
2207 struct listnode *node;
2208
2209 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2210 ALOGV("%s:napb: not in true mode or non hdphones device",
2211 __func__);
2212 active = false;
2213 goto exit;
2214 }
2215
2216 list_for_each(node, &adev->usecase_list) {
2217 struct audio_usecase *uc;
2218 uc = node_to_item(node, struct audio_usecase, list);
2219 struct stream_out *curr_out =
2220 (struct stream_out*) uc->stream.out;
2221
2222 if (curr_out && PCM_PLAYBACK == uc->type) {
2223 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2224 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2225 uc->id, curr_out->sample_rate,
2226 curr_out->bit_width,
2227 platform_get_snd_device_name(uc->out_snd_device));
2228
2229 if (is_offload_usecase(uc->id) &&
2230 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2231 active = true;
2232 ALOGD("%s:napb:native stream detected", __func__);
2233 }
2234 }
2235 }
2236exit:
2237 return active;
2238}
2239
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002240uint32_t adev_get_dsp_bit_width_enforce_mode()
2241{
2242 if (adev == NULL) {
2243 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2244 return 0;
2245 }
2246 return adev->dsp_bit_width_enforce_mode;
2247}
2248
2249static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2250{
2251 char value[PROPERTY_VALUE_MAX];
2252 int trial;
2253 uint32_t dsp_bit_width_enforce_mode = 0;
2254
2255 if (!mixer) {
2256 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2257 __func__);
2258 return 0;
2259 }
2260
2261 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2262 value, NULL) > 0) {
2263 trial = atoi(value);
2264 switch (trial) {
2265 case 16:
2266 dsp_bit_width_enforce_mode = 16;
2267 break;
2268 case 24:
2269 dsp_bit_width_enforce_mode = 24;
2270 break;
2271 case 32:
2272 dsp_bit_width_enforce_mode = 32;
2273 break;
2274 default:
2275 dsp_bit_width_enforce_mode = 0;
2276 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2277 break;
2278 }
2279 }
2280
2281 return dsp_bit_width_enforce_mode;
2282}
2283
2284static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2285 uint32_t enforce_mode,
2286 bool enable)
2287{
2288 struct mixer_ctl *ctl = NULL;
2289 const char *mixer_ctl_name = "ASM Bit Width";
2290 uint32_t asm_bit_width_mode = 0;
2291
2292 if (enforce_mode == 0) {
2293 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2294 return;
2295 }
2296
2297 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2298 if (!ctl) {
2299 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2300 __func__, mixer_ctl_name);
2301 return;
2302 }
2303
2304 if (enable)
2305 asm_bit_width_mode = enforce_mode;
2306 else
2307 asm_bit_width_mode = 0;
2308
2309 ALOGV("%s DSP bit width feature status is %d width=%d",
2310 __func__, enable, asm_bit_width_mode);
2311 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2312 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2313 asm_bit_width_mode);
2314
2315 return;
2316}
2317
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302318/*
2319 * if native DSD playback active
2320 */
2321bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2322{
2323 bool active = false;
2324 struct listnode *node = NULL;
2325 struct audio_usecase *uc = NULL;
2326 struct stream_out *curr_out = NULL;
2327
2328 list_for_each(node, &adev->usecase_list) {
2329 uc = node_to_item(node, struct audio_usecase, list);
2330 curr_out = (struct stream_out*) uc->stream.out;
2331
2332 if (curr_out && PCM_PLAYBACK == uc->type &&
2333 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2334 active = true;
2335 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302336 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302337 }
2338 }
2339 return active;
2340}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302341
2342static bool force_device_switch(struct audio_usecase *usecase)
2343{
2344 bool ret = false;
2345 bool is_it_true_mode = false;
2346
Zhou Song30f2c3e2018-02-08 14:02:15 +08002347 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302348 usecase->type == TRANSCODE_LOOPBACK_RX ||
2349 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002350 return false;
2351 }
2352
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002353 if(usecase->stream.out == NULL) {
2354 ALOGE("%s: stream.out is NULL", __func__);
2355 return false;
2356 }
2357
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302358 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002359 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002360 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2361 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302362 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2363 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2364 (!is_it_true_mode && adev->native_playback_enabled)){
2365 ret = true;
2366 ALOGD("napb: time to toggle native mode");
2367 }
2368 }
2369
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302370 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302371 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2372 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002373 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302374 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302375 ALOGD("Force a2dp device switch to update new encoder config");
2376 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002377 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302378
Florian Pfister1a84f312018-07-19 14:38:18 +02002379 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302380 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2381 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002382 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302383 return ret;
2384}
2385
Aalique Grahame22e49102018-12-18 14:23:57 -08002386static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2387{
2388 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2389}
2390
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302391bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2392{
2393 bool ret=false;
2394 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002395 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2396 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302397 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2398 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002399 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302400 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002401 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2402 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302403 ret = true;
2404
2405 return ret;
2406}
2407
2408bool is_a2dp_device(snd_device_t out_snd_device)
2409{
2410 bool ret=false;
2411 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2412 ret = true;
2413
2414 return ret;
2415}
2416
2417bool is_bt_soc_on(struct audio_device *adev)
2418{
2419 struct mixer_ctl *ctl;
2420 char *mixer_ctl_name = "BT SOC status";
2421 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2422 bool bt_soc_status = true;
2423 if (!ctl) {
2424 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2425 __func__, mixer_ctl_name);
2426 /*This is to ensure we dont break targets which dont have the kernel change*/
2427 return true;
2428 }
2429 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2430 ALOGD("BT SOC status: %d",bt_soc_status);
2431 return bt_soc_status;
2432}
2433
Zhou Song331c8e52019-08-26 14:16:12 +08002434static int configure_btsco_sample_rate(snd_device_t snd_device)
2435{
2436 struct mixer_ctl *ctl = NULL;
2437 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2438 char *rate_str = NULL;
2439 bool is_rx_dev = true;
2440
2441 if (is_btsco_device(snd_device, snd_device)) {
2442 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2443 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2444 if (!ctl_sr_tx || !ctl_sr_rx) {
2445 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2446 if (!ctl_sr)
2447 return -ENOSYS;
2448 }
2449
2450 switch (snd_device) {
2451 case SND_DEVICE_OUT_BT_SCO:
2452 rate_str = "KHZ_8";
2453 break;
2454 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2455 case SND_DEVICE_IN_BT_SCO_MIC:
2456 rate_str = "KHZ_8";
2457 is_rx_dev = false;
2458 break;
2459 case SND_DEVICE_OUT_BT_SCO_WB:
2460 rate_str = "KHZ_16";
2461 break;
2462 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2463 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2464 rate_str = "KHZ_16";
2465 is_rx_dev = false;
2466 break;
2467 default:
2468 return 0;
2469 }
2470
2471 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2472 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2473 return -ENOSYS;
2474 }
2475 return 0;
2476}
2477
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302478int out_standby_l(struct audio_stream *stream);
2479
Eric Laurent637e2d42018-11-15 12:24:31 -08002480struct stream_in *adev_get_active_input(const struct audio_device *adev)
2481{
2482 struct listnode *node;
2483 struct stream_in *last_active_in = NULL;
2484
2485 /* Get last added active input.
2486 * TODO: We may use a priority mechanism to pick highest priority active source */
2487 list_for_each(node, &adev->usecase_list)
2488 {
2489 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2490 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2491 last_active_in = usecase->stream.in;
2492 }
2493
2494 return last_active_in;
2495}
2496
2497struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2498{
2499 struct listnode *node;
2500
2501 /* First check active inputs with voice communication source and then
2502 * any input if audio mode is in communication */
2503 list_for_each(node, &adev->usecase_list)
2504 {
2505 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2506 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2507 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2508 return usecase->stream.in;
2509 }
2510 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2511 return adev_get_active_input(adev);
2512
2513 return NULL;
2514}
2515
Carter Hsu2e429db2019-05-14 18:50:52 +08002516/*
2517 * Aligned with policy.h
2518 */
2519static inline int source_priority(int inputSource)
2520{
2521 switch (inputSource) {
2522 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2523 return 9;
2524 case AUDIO_SOURCE_CAMCORDER:
2525 return 8;
2526 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2527 return 7;
2528 case AUDIO_SOURCE_UNPROCESSED:
2529 return 6;
2530 case AUDIO_SOURCE_MIC:
2531 return 5;
2532 case AUDIO_SOURCE_ECHO_REFERENCE:
2533 return 4;
2534 case AUDIO_SOURCE_FM_TUNER:
2535 return 3;
2536 case AUDIO_SOURCE_VOICE_RECOGNITION:
2537 return 2;
2538 case AUDIO_SOURCE_HOTWORD:
2539 return 1;
2540 default:
2541 break;
2542 }
2543 return 0;
2544}
2545
2546static struct stream_in *get_priority_input(struct audio_device *adev)
2547{
2548 struct listnode *node;
2549 struct audio_usecase *usecase;
2550 int last_priority = 0, priority;
2551 struct stream_in *priority_in = NULL;
2552 struct stream_in *in;
2553
2554 list_for_each(node, &adev->usecase_list) {
2555 usecase = node_to_item(node, struct audio_usecase, list);
2556 if (usecase->type == PCM_CAPTURE) {
2557 in = usecase->stream.in;
2558 if (!in)
2559 continue;
2560 priority = source_priority(in->source);
2561
2562 if (priority > last_priority) {
2563 last_priority = priority;
2564 priority_in = in;
2565 }
2566 }
2567 }
2568 return priority_in;
2569}
2570
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002571int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002573 snd_device_t out_snd_device = SND_DEVICE_NONE;
2574 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002575 struct audio_usecase *usecase = NULL;
2576 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002577 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002578 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302579 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002580 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002581 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302583 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2584
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002585 usecase = get_usecase_from_list(adev, uc_id);
2586 if (usecase == NULL) {
2587 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2588 return -EINVAL;
2589 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002591 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002592 (usecase->type == VOIP_CALL) ||
2593 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302594 if(usecase->stream.out == NULL) {
2595 ALOGE("%s: stream.out is NULL", __func__);
2596 return -EINVAL;
2597 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002598 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002599 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2600 uc_id);
2601 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2602 uc_id);
2603 } else {
2604 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302605 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002606 in_snd_device = platform_get_input_snd_device(adev->platform,
2607 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302608 &usecase->stream.out->device_list,
2609 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002610 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002611 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302612 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302613 if (usecase->stream.inout == NULL) {
2614 ALOGE("%s: stream.inout is NULL", __func__);
2615 return -EINVAL;
2616 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002617 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302618 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2619 stream_out.format = usecase->stream.inout->out_config.format;
2620 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302621 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002622 assign_devices(&usecase->device_list,
2623 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302624 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2625 if (usecase->stream.inout == NULL) {
2626 ALOGE("%s: stream.inout is NULL", __func__);
2627 return -EINVAL;
2628 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302629 struct listnode out_devices;
2630 list_init(&out_devices);
2631 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2632 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002633 assign_devices(&usecase->device_list,
2634 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002635 } else {
2636 /*
2637 * If the voice call is active, use the sound devices of voice call usecase
2638 * so that it would not result any device switch. All the usecases will
2639 * be switched to new device when select_devices() is called for voice call
2640 * usecase. This is to avoid switching devices for voice call when
2641 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002642 * choose voice call device only if the use case device is
2643 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002644 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002645 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002646 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002647 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002648 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2649 is_codec_backend_out_device_type(&usecase->device_list)) ||
2650 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2651 is_codec_backend_in_device_type(&usecase->device_list)) ||
2652 is_single_device_type_equal(&vc_usecase->device_list,
2653 AUDIO_DEVICE_OUT_HEARING_AID) ||
2654 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002655 AUDIO_DEVICE_IN_VOICE_CALL) ||
2656 (is_single_device_type_equal(&usecase->device_list,
2657 AUDIO_DEVICE_IN_USB_HEADSET) &&
2658 is_single_device_type_equal(&vc_usecase->device_list,
2659 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002660 in_snd_device = vc_usecase->in_snd_device;
2661 out_snd_device = vc_usecase->out_snd_device;
2662 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002663 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002664 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002665 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002666 if ((voip_usecase != NULL) &&
2667 (usecase->type == PCM_PLAYBACK) &&
2668 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002669 out_snd_device_backend_match = platform_check_backends_match(
2670 voip_usecase->out_snd_device,
2671 platform_get_output_snd_device(
2672 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302673 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002674 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002675 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2676 (is_codec_backend_out_device_type(&usecase->device_list) ||
2677 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002678 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002679 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002680 in_snd_device = voip_usecase->in_snd_device;
2681 out_snd_device = voip_usecase->out_snd_device;
2682 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002683 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002684 hfp_ucid = audio_extn_hfp_get_usecase();
2685 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002686 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002687 in_snd_device = hfp_usecase->in_snd_device;
2688 out_snd_device = hfp_usecase->out_snd_device;
2689 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002690 }
2691 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302692 if (usecase->stream.out == NULL) {
2693 ALOGE("%s: stream.out is NULL", __func__);
2694 return -EINVAL;
2695 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002696 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002697 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002698 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002699 struct stream_out *voip_out = adev->primary_output;
2700 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002701 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002702 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2703 else
2704 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302705 usecase->stream.out,
2706 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002707 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002708
Eric Laurent637e2d42018-11-15 12:24:31 -08002709 if (voip_usecase)
2710 voip_out = voip_usecase->stream.out;
2711
2712 if (usecase->stream.out == voip_out && voip_in != NULL)
2713 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002714 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002715 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302716 if (usecase->stream.in == NULL) {
2717 ALOGE("%s: stream.in is NULL", __func__);
2718 return -EINVAL;
2719 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002720 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002721 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002722 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002723 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002724 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002725 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002726
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002727 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002728 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002729 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2730 USECASE_AUDIO_PLAYBACK_VOIP);
2731
Carter Hsu2e429db2019-05-14 18:50:52 +08002732 usecase->stream.in->enable_ec_port = false;
2733
Zhou Song62ea0282020-03-22 19:53:01 +08002734 bool is_ha_usecase = adev->ha_proxy_enable ?
2735 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2736 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2737 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002738 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002739 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002740 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002741 } else if (adev->primary_output &&
2742 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002743 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002744 } else {
2745 /* forcing speaker o/p device to get matching i/p pair
2746 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002747 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002748 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002749 priority_in = voip_in;
2750 } else {
2751 /* get the input with the highest priority source*/
2752 priority_in = get_priority_input(adev);
2753
2754 if (!priority_in)
2755 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002756 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002757
Eric Laurent637e2d42018-11-15 12:24:31 -08002758 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002759 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302760 &out_devices,
2761 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002762 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002763 }
2764 }
2765
2766 if (out_snd_device == usecase->out_snd_device &&
2767 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302768
2769 if (!force_device_switch(usecase))
2770 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771 }
2772
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002773 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002774 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002775 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002776 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2777 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302778 }
2779
Aalique Grahame22e49102018-12-18 14:23:57 -08002780 if (out_snd_device != SND_DEVICE_NONE &&
2781 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2782 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2783 __func__,
2784 use_case_table[uc_id],
2785 adev->last_logged_snd_device[uc_id][0],
2786 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2787 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2788 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2789 -1,
2790 out_snd_device,
2791 platform_get_snd_device_name(out_snd_device),
2792 platform_get_snd_device_acdb_id(out_snd_device));
2793 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2794 }
2795 if (in_snd_device != SND_DEVICE_NONE &&
2796 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2797 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2798 __func__,
2799 use_case_table[uc_id],
2800 adev->last_logged_snd_device[uc_id][1],
2801 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2802 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2803 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2804 -1,
2805 in_snd_device,
2806 platform_get_snd_device_name(in_snd_device),
2807 platform_get_snd_device_acdb_id(in_snd_device));
2808 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2809 }
2810
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812 /*
2813 * Limitation: While in call, to do a device switch we need to disable
2814 * and enable both RX and TX devices though one of them is same as current
2815 * device.
2816 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002817 if ((usecase->type == VOICE_CALL) &&
2818 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2819 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002820 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002821 }
2822
2823 if (((usecase->type == VOICE_CALL) ||
2824 (usecase->type == VOIP_CALL)) &&
2825 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2826 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302827 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002828 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002829 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002830
2831 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302832 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002833 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002834 }
2835
Aalique Grahame22e49102018-12-18 14:23:57 -08002836 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2837 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002838 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302839 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002840 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2841 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2842 else
2843 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302844 }
2845
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002846 /* Disable current sound devices */
2847 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002848 disable_audio_route(adev, usecase);
2849 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002850 }
2851
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002852 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002853 disable_audio_route(adev, usecase);
2854 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855 }
2856
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002857 /* Applicable only on the targets that has external modem.
2858 * New device information should be sent to modem before enabling
2859 * the devices to reduce in-call device switch time.
2860 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002861 if ((usecase->type == VOICE_CALL) &&
2862 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2863 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002864 status = platform_switch_voice_call_enable_device_config(adev->platform,
2865 out_snd_device,
2866 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002867 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002868
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002869 /* Enable new sound devices */
2870 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002871 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302872 if (platform_check_codec_asrc_support(adev->platform))
2873 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002874 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 }
2876
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002877 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302878 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002879 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002880 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002881
Avinash Vaish71a8b972014-07-24 15:36:33 +05302882 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002883 status = platform_switch_voice_call_device_post(adev->platform,
2884 out_snd_device,
2885 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302886 enable_audio_route_for_voice_usecases(adev, usecase);
2887 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002888
sangwoo170731f2013-06-08 15:36:36 +09002889 usecase->in_snd_device = in_snd_device;
2890 usecase->out_snd_device = out_snd_device;
2891
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302892 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2893 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302894 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002895 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002896 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002897 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2898 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2899 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2900 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2901 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2902 /*
2903 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2904 * configured device sample rate, if not update the COPP rate to be equal to the
2905 * device sample rate, else open COPP at stream sample rate
2906 */
2907 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2908 usecase->stream.out->sample_rate,
2909 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302910 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302911 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2912 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302913 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002914 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2915 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2916 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2917 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002918 }
2919 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002920
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002921 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002922
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002923 /* If input stream is already running then effect needs to be
2924 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002925 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002926 check_and_enable_effect(adev);
2927
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002928 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002929 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302930 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002931 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2932
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002933 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302934 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002935 voice_extn_compress_voip_is_started(adev))
2936 voice_set_sidetone(adev, out_snd_device, true);
2937 }
2938
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002939 /* Applicable only on the targets that has external modem.
2940 * Enable device command should be sent to modem only after
2941 * enabling voice call mixer controls
2942 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002943 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002944 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2945 out_snd_device,
2946 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302947
2948 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002949 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302950 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002951 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302952 if (is_bt_soc_on(adev) == false){
2953 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002954 if (in->pcm != NULL)
2955 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302956 }
2957 }
2958 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2959 && usecase->stream.out->started) {
2960 if (is_bt_soc_on(adev) == false) {
2961 ALOGD("BT SCO/A2DP disconnected while in connection");
2962 out_standby_l(&usecase->stream.out->stream.common);
2963 }
2964 }
2965 } else if ((usecase->stream.out != NULL) &&
2966 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302967 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2968 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08002969 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302970 usecase->stream.out->started) {
2971 if (is_bt_soc_on(adev) == false) {
2972 ALOGD("BT SCO/A2dp disconnected while in connection");
2973 out_standby_l(&usecase->stream.out->stream.common);
2974 }
2975 }
2976 }
2977
Yung Ti Su70cb8242018-06-22 17:38:47 +08002978 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002979 struct stream_out *voip_out = voip_usecase->stream.out;
2980 audio_extn_utils_send_app_type_gain(adev,
2981 voip_out->app_type_cfg.app_type,
2982 &voip_out->app_type_cfg.gain[0]);
2983 }
2984
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302985 ALOGD("%s: done",__func__);
2986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987 return status;
2988}
2989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990static int stop_input_stream(struct stream_in *in)
2991{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302992 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302994
2995 if (in == NULL) {
2996 ALOGE("%s: stream_in ptr is NULL", __func__);
2997 return -EINVAL;
2998 }
2999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003001 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002
Eric Laurent994a6932013-07-17 11:51:42 -07003003 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003004 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 uc_info = get_usecase_from_list(adev, in->usecase);
3006 if (uc_info == NULL) {
3007 ALOGE("%s: Could not find the usecase (%d) in the list",
3008 __func__, in->usecase);
3009 return -EINVAL;
3010 }
3011
Carter Hsu2e429db2019-05-14 18:50:52 +08003012 priority_in = get_priority_input(adev);
3013
Derek Chenea197282019-01-07 17:35:01 -08003014 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3015 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003016
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003017 /* Close in-call recording streams */
3018 voice_check_and_stop_incall_rec_usecase(adev, in);
3019
Eric Laurent150dbfe2013-02-27 14:31:02 -08003020 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003021 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003022
3023 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003024 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003026 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303027 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3028
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003029 list_remove(&uc_info->list);
3030 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031
Carter Hsu2e429db2019-05-14 18:50:52 +08003032 if (priority_in == in) {
3033 priority_in = get_priority_input(adev);
3034 if (priority_in)
3035 select_devices(adev, priority_in->usecase);
3036 }
3037
Vatsal Buchac09ae062018-11-14 13:25:08 +05303038 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003039 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 return ret;
3041}
3042
3043int start_input_stream(struct stream_in *in)
3044{
3045 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003046 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303048
3049 if (in == NULL) {
3050 ALOGE("%s: stream_in ptr is NULL", __func__);
3051 return -EINVAL;
3052 }
3053
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003055 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003056 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057
Mingming Yin2664a5b2015-09-03 10:53:11 -07003058 if (get_usecase_from_list(adev, usecase) == NULL)
3059 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303060 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3061 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003062
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303063 if (CARD_STATUS_OFFLINE == in->card_status||
3064 CARD_STATUS_OFFLINE == adev->card_status) {
3065 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303066 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303067 goto error_config;
3068 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303069
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003070 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303071 if (!adev->bt_sco_on) {
3072 ALOGE("%s: SCO profile is not ready, return error", __func__);
3073 ret = -EIO;
3074 goto error_config;
3075 }
3076 }
3077
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003078 /* Check if source matches incall recording usecase criteria */
3079 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3080 if (ret)
3081 goto error_config;
3082 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003083 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3084
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303085 if (audio_extn_cin_attached_usecase(in))
3086 audio_extn_cin_acquire_usecase(in);
3087
Mingming Yin2664a5b2015-09-03 10:53:11 -07003088 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3089 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3090 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003091 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003092 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003093
Eric Laurentb23d5282013-05-14 15:27:20 -07003094 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 if (in->pcm_device_id < 0) {
3096 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3097 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003098 ret = -EINVAL;
3099 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003103
3104 if (!uc_info) {
3105 ret = -ENOMEM;
3106 goto error_config;
3107 }
3108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109 uc_info->id = in->usecase;
3110 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003111 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003112 list_init(&uc_info->device_list);
3113 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003114 uc_info->in_snd_device = SND_DEVICE_NONE;
3115 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003117 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003118 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303119 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3120 adev->perf_lock_opts,
3121 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003122 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123
Derek Chenea197282019-01-07 17:35:01 -08003124 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3125 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003126
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303127 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3128
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303129 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303130 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303131 if (ret)
3132 goto error_open;
3133 else
3134 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003135 }
3136
Haynes Mathew George16081042017-05-31 17:16:49 -07003137 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003138 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003139 ALOGE("%s: pcm stream not ready", __func__);
3140 goto error_open;
3141 }
3142 ret = pcm_start(in->pcm);
3143 if (ret < 0) {
3144 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3145 goto error_open;
3146 }
3147 } else {
3148 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3149 unsigned int pcm_open_retry_count = 0;
3150
Zhou Song62ea0282020-03-22 19:53:01 +08003151 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3152 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003153 flags |= PCM_MMAP | PCM_NOIRQ;
3154 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3155 } else if (in->realtime) {
3156 flags |= PCM_MMAP | PCM_NOIRQ;
3157 }
3158
Garmond Leunge2433c32017-09-28 21:51:22 -07003159 if (audio_extn_ffv_get_stream() == in) {
3160 ALOGD("%s: ffv stream, update pcm config", __func__);
3161 audio_extn_ffv_update_pcm_config(&config);
3162 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003163 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3164 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3165
3166 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003167 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003168 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003169 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003170 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303171 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303172 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3173 adev->card_status = CARD_STATUS_OFFLINE;
3174 in->card_status = CARD_STATUS_OFFLINE;
3175 ret = -EIO;
3176 goto error_open;
3177 }
3178
Haynes Mathew George16081042017-05-31 17:16:49 -07003179 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3180 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3181 if (in->pcm != NULL) {
3182 pcm_close(in->pcm);
3183 in->pcm = NULL;
3184 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003185 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003186 ret = -EIO;
3187 goto error_open;
3188 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003189 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003190 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3191 continue;
3192 }
3193 break;
3194 }
3195
3196 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003197 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003198 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003199 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003200 if (ret < 0) {
3201 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3202 pcm_close(in->pcm);
3203 in->pcm = NULL;
3204 goto error_open;
3205 }
3206 register_in_stream(in);
3207 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003208 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003209 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003210 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003211 if (ret < 0) {
3212 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003213 pcm_close(in->pcm);
3214 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003215 goto error_open;
3216 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003217 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003218 }
3219
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003220 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003221 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3222 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003223
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003224 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303225 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3226
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303227done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003228 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303229 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003230 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303231 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003232 return ret;
3233
3234error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003235 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303236 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003238
Eric Laurentc8400632013-02-14 19:04:54 -08003239error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303240 /*
3241 * sleep 50ms to allow sufficient time for kernel
3242 * drivers to recover incases like SSR.
3243 */
3244 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003245 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303246 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003247 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248}
3249
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003250void lock_input_stream(struct stream_in *in)
3251{
3252 pthread_mutex_lock(&in->pre_lock);
3253 pthread_mutex_lock(&in->lock);
3254 pthread_mutex_unlock(&in->pre_lock);
3255}
3256
3257void lock_output_stream(struct stream_out *out)
3258{
3259 pthread_mutex_lock(&out->pre_lock);
3260 pthread_mutex_lock(&out->lock);
3261 pthread_mutex_unlock(&out->pre_lock);
3262}
3263
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003264/* must be called with out->lock locked */
3265static int send_offload_cmd_l(struct stream_out* out, int command)
3266{
3267 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3268
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003269 if (!cmd) {
3270 ALOGE("failed to allocate mem for command 0x%x", command);
3271 return -ENOMEM;
3272 }
3273
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003274 ALOGVV("%s %d", __func__, command);
3275
3276 cmd->cmd = command;
3277 list_add_tail(&out->offload_cmd_list, &cmd->node);
3278 pthread_cond_signal(&out->offload_cond);
3279 return 0;
3280}
3281
3282/* must be called iwth out->lock locked */
3283static void stop_compressed_output_l(struct stream_out *out)
3284{
3285 out->offload_state = OFFLOAD_STATE_IDLE;
3286 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003287 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003288 if (out->compr != NULL) {
3289 compress_stop(out->compr);
3290 while (out->offload_thread_blocked) {
3291 pthread_cond_wait(&out->cond, &out->lock);
3292 }
3293 }
3294}
3295
Varun Balaraje49253e2017-07-06 19:48:56 +05303296bool is_interactive_usecase(audio_usecase_t uc_id)
3297{
3298 unsigned int i;
3299 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3300 if (uc_id == interactive_usecases[i])
3301 return true;
3302 }
3303 return false;
3304}
3305
3306static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3307{
3308 audio_usecase_t ret_uc = USECASE_INVALID;
3309 unsigned int intract_uc_index;
3310 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3311
3312 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3313 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3314 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3315 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3316 ret_uc = interactive_usecases[intract_uc_index];
3317 break;
3318 }
3319 }
3320
3321 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3322 return ret_uc;
3323}
3324
3325static void free_interactive_usecase(struct audio_device *adev,
3326 audio_usecase_t uc_id)
3327{
3328 unsigned int interact_uc_index;
3329 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3330
3331 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3332 if (interactive_usecases[interact_uc_index] == uc_id) {
3333 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3334 break;
3335 }
3336 }
3337 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3338}
3339
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003340bool is_offload_usecase(audio_usecase_t uc_id)
3341{
3342 unsigned int i;
3343 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3344 if (uc_id == offload_usecases[i])
3345 return true;
3346 }
3347 return false;
3348}
3349
Dhananjay Kumarac341582017-02-23 23:42:25 +05303350static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003351{
vivek mehta446c3962015-09-14 10:57:35 -07003352 audio_usecase_t ret_uc = USECASE_INVALID;
3353 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003354 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003355 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303356 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003357 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3358 else
3359 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003360
vivek mehta446c3962015-09-14 10:57:35 -07003361 pthread_mutex_lock(&adev->lock);
3362 if (get_usecase_from_list(adev, ret_uc) != NULL)
3363 ret_uc = USECASE_INVALID;
3364 pthread_mutex_unlock(&adev->lock);
3365
3366 return ret_uc;
3367 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003368
3369 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003370 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3371 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3372 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3373 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003374 break;
3375 }
3376 }
vivek mehta446c3962015-09-14 10:57:35 -07003377
3378 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3379 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003380}
3381
3382static void free_offload_usecase(struct audio_device *adev,
3383 audio_usecase_t uc_id)
3384{
vivek mehta446c3962015-09-14 10:57:35 -07003385 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003386 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003387
3388 if (!adev->multi_offload_enable)
3389 return;
3390
3391 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3392 if (offload_usecases[offload_uc_index] == uc_id) {
3393 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003394 break;
3395 }
3396 }
3397 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3398}
3399
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003400static void *offload_thread_loop(void *context)
3401{
3402 struct stream_out *out = (struct stream_out *) context;
3403 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003404 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003405
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003406 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003407 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003408 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3409
3410 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003411 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003412 out->offload_state = OFFLOAD_STATE_IDLE;
3413 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003414 for (;;) {
3415 struct offload_cmd *cmd = NULL;
3416 stream_callback_event_t event;
3417 bool send_callback = false;
3418
3419 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3420 __func__, list_empty(&out->offload_cmd_list),
3421 out->offload_state);
3422 if (list_empty(&out->offload_cmd_list)) {
3423 ALOGV("%s SLEEPING", __func__);
3424 pthread_cond_wait(&out->offload_cond, &out->lock);
3425 ALOGV("%s RUNNING", __func__);
3426 continue;
3427 }
3428
3429 item = list_head(&out->offload_cmd_list);
3430 cmd = node_to_item(item, struct offload_cmd, node);
3431 list_remove(item);
3432
3433 ALOGVV("%s STATE %d CMD %d out->compr %p",
3434 __func__, out->offload_state, cmd->cmd, out->compr);
3435
3436 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3437 free(cmd);
3438 break;
3439 }
3440
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003441 // allow OFFLOAD_CMD_ERROR reporting during standby
3442 // this is needed to handle failures during compress_open
3443 // Note however that on a pause timeout, the stream is closed
3444 // and no offload usecase will be active. Therefore this
3445 // special case is needed for compress_open failures alone
3446 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3447 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003448 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003449 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003450 pthread_cond_signal(&out->cond);
3451 continue;
3452 }
3453 out->offload_thread_blocked = true;
3454 pthread_mutex_unlock(&out->lock);
3455 send_callback = false;
3456 switch(cmd->cmd) {
3457 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003458 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003459 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003460 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003461 send_callback = true;
3462 event = STREAM_CBK_EVENT_WRITE_READY;
3463 break;
3464 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003465 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303466 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003467 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303468 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003469 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303470 if (ret < 0)
3471 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303472 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303473 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003474 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003475 else
3476 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003477 if (-ENETRESET != ret && !(-EINTR == ret &&
3478 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303479 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303480 pthread_mutex_lock(&out->lock);
3481 out->send_new_metadata = 1;
3482 out->send_next_track_params = true;
3483 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303484 event = STREAM_CBK_EVENT_DRAIN_READY;
3485 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3486 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303487 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003488 break;
3489 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003490 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003491 ret = compress_drain(out->compr);
3492 ALOGD("copl(%p):out of compress_drain", out);
3493 // EINTR check avoids drain interruption due to SSR
3494 if (-ENETRESET != ret && !(-EINTR == ret &&
3495 CARD_STATUS_OFFLINE == out->card_status)) {
3496 send_callback = true;
3497 event = STREAM_CBK_EVENT_DRAIN_READY;
3498 } else
3499 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003500 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303501 case OFFLOAD_CMD_ERROR:
3502 ALOGD("copl(%p): sending error callback to AF", out);
3503 send_callback = true;
3504 event = STREAM_CBK_EVENT_ERROR;
3505 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003506 default:
3507 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3508 break;
3509 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003510 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003511 out->offload_thread_blocked = false;
3512 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003513 if (send_callback && out->client_callback) {
3514 ALOGVV("%s: sending client_callback event %d", __func__, event);
3515 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003516 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003517 free(cmd);
3518 }
3519
3520 pthread_cond_signal(&out->cond);
3521 while (!list_empty(&out->offload_cmd_list)) {
3522 item = list_head(&out->offload_cmd_list);
3523 list_remove(item);
3524 free(node_to_item(item, struct offload_cmd, node));
3525 }
3526 pthread_mutex_unlock(&out->lock);
3527
3528 return NULL;
3529}
3530
3531static int create_offload_callback_thread(struct stream_out *out)
3532{
3533 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3534 list_init(&out->offload_cmd_list);
3535 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3536 offload_thread_loop, out);
3537 return 0;
3538}
3539
3540static int destroy_offload_callback_thread(struct stream_out *out)
3541{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003542 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003543 stop_compressed_output_l(out);
3544 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3545
3546 pthread_mutex_unlock(&out->lock);
3547 pthread_join(out->offload_thread, (void **) NULL);
3548 pthread_cond_destroy(&out->offload_cond);
3549
3550 return 0;
3551}
3552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553static int stop_output_stream(struct stream_out *out)
3554{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303555 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 struct audio_usecase *uc_info;
3557 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003558 bool has_voip_usecase =
3559 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560
Eric Laurent994a6932013-07-17 11:51:42 -07003561 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003562 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 uc_info = get_usecase_from_list(adev, out->usecase);
3564 if (uc_info == NULL) {
3565 ALOGE("%s: Could not find the usecase (%d) in the list",
3566 __func__, out->usecase);
3567 return -EINVAL;
3568 }
3569
Derek Chenea197282019-01-07 17:35:01 -08003570 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3571 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003572
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003573 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303574 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003575 if (adev->visualizer_stop_output != NULL)
3576 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003577
3578 audio_extn_dts_remove_state_notifier_node(out->usecase);
3579
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003580 if (adev->offload_effects_stop_output != NULL)
3581 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003582 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3583 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3584 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003585 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003586
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003587 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3588 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003589 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003590 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003591
Eric Laurent150dbfe2013-02-27 14:31:02 -08003592 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003593 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003594
3595 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003596 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597
Aalique Grahame22e49102018-12-18 14:23:57 -08003598 audio_extn_extspk_update(adev->extspk);
3599
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003600 if (is_offload_usecase(out->usecase)) {
3601 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3602 adev->dsp_bit_width_enforce_mode,
3603 false);
3604 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003605 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003606 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3607 false);
3608
3609 if (ret != 0)
3610 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3611 /* default service interval was successfully updated,
3612 reopen USB backend with new service interval */
3613 ret = 0;
3614 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003615
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003616 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303617 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003618 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303619 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003620 ALOGV("Disable passthrough , reset mixer to pcm");
3621 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003622#ifdef AUDIO_GKI_ENABLED
3623 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3624 out->compr_config.codec->reserved[0] = 0;
3625#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003626 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003627#endif
Mingming Yin21854652016-04-13 11:54:02 -07003628 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003629 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3630 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003631
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303632 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003633 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303634 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303635
Manish Dewangan21a850a2017-08-14 12:03:55 +05303636 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003637 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3638 if (ret < 0)
3639 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3640 }
3641
juyuchen2d415992018-11-16 14:15:16 +08003642 /* 1) media + voip output routing to handset must route media back to
3643 speaker when voip stops.
3644 2) trigger voip input to reroute when voip output changes to
3645 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003646 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003647 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003648 struct listnode *node;
3649 struct audio_usecase *usecase;
3650 list_for_each(node, &adev->usecase_list) {
3651 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003652 if ((usecase->type == PCM_CAPTURE &&
3653 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3654 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003655 continue;
3656
3657 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3658 __func__, usecase->id, use_case_table[usecase->id],
3659 out->usecase, use_case_table[out->usecase]);
3660 select_devices(adev, usecase->id);
3661 }
3662 }
3663
Garmond Leung5fd0b552018-04-17 11:56:12 -07003664 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003665 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003666 return ret;
3667}
3668
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003669struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3670 unsigned int flags, unsigned int pcm_open_retry_count,
3671 struct pcm_config *config)
3672{
3673 struct pcm* pcm = NULL;
3674
3675 while (1) {
3676 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3677 if (pcm == NULL || !pcm_is_ready(pcm)) {
3678 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3679 if (pcm != NULL) {
3680 pcm_close(pcm);
3681 pcm = NULL;
3682 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003683 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003684 return NULL;
3685
Weiyin Jiang72197252019-10-09 11:49:32 +08003686 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003687 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3688 continue;
3689 }
3690 break;
3691 }
3692
3693 if (pcm_is_ready(pcm)) {
3694 int ret = pcm_prepare(pcm);
3695 if (ret < 0) {
3696 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3697 pcm_close(pcm);
3698 pcm = NULL;
3699 }
3700 }
3701
3702 return pcm;
3703}
3704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705int start_output_stream(struct stream_out *out)
3706{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 struct audio_usecase *uc_info;
3709 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003710 char mixer_ctl_name[128];
3711 struct mixer_ctl *ctl = NULL;
3712 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303713 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003714 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715
Haynes Mathew George380745d2017-10-04 15:27:45 -07003716 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003717 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3718 ret = -EINVAL;
3719 goto error_config;
3720 }
3721
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003722 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303723 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003724 get_device_types(&out->device_list), is_haptic_usecase);
3725
3726 bool is_speaker_active = compare_device_type(&out->device_list,
3727 AUDIO_DEVICE_OUT_SPEAKER);
3728 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3729 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303730
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303731 if (CARD_STATUS_OFFLINE == out->card_status ||
3732 CARD_STATUS_OFFLINE == adev->card_status) {
3733 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303734 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003735 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303736 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303737
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003738 //Update incall music usecase to reflect correct voice session
3739 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3740 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3741 if (ret != 0) {
3742 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3743 __func__, ret);
3744 goto error_config;
3745 }
3746 }
3747
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003748 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003749 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003750 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303751 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303752 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303753 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3754 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3755 ret = -EAGAIN;
3756 goto error_config;
3757 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303758 }
3759 }
3760 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003761 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303762 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003763 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303764 //combo usecase just by pass a2dp
3765 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003766 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303767 } else {
3768 ALOGE("%s: SCO profile is not ready, return error", __func__);
3769 ret = -EAGAIN;
3770 goto error_config;
3771 }
3772 }
3773 }
3774
Eric Laurentb23d5282013-05-14 15:27:20 -07003775 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776 if (out->pcm_device_id < 0) {
3777 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3778 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003779 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003780 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 }
3782
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003783 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003784 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3785 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003786 if (adev->haptic_pcm_device_id < 0) {
3787 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3788 __func__, adev->haptic_pcm_device_id, out->usecase);
3789 ret = -EINVAL;
3790 goto error_config;
3791 }
3792 }
3793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003795
3796 if (!uc_info) {
3797 ret = -ENOMEM;
3798 goto error_config;
3799 }
3800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 uc_info->id = out->usecase;
3802 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003803 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003804 list_init(&uc_info->device_list);
3805 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003806 uc_info->in_snd_device = SND_DEVICE_NONE;
3807 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003808
3809 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003810 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003811 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3812 /* USB backend is not reopened immediately.
3813 This is eventually done as part of select_devices */
3814 }
3815
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003816 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817
Wei Wangf7ca6c92017-11-21 14:51:20 -08003818 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303819 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3820 adev->perf_lock_opts,
3821 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303822
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003823 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303824 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303825 if (audio_extn_passthru_is_enabled() &&
3826 audio_extn_passthru_is_passthrough_stream(out)) {
3827 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303828 }
3829 }
3830
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003831 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003832 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303833 if (!a2dp_combo) {
3834 check_a2dp_restore_l(adev, out, false);
3835 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003836 struct listnode dev;
3837 list_init(&dev);
3838 assign_devices(&dev, &out->device_list);
3839 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3840 reassign_device_list(&out->device_list,
3841 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003842 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003843 reassign_device_list(&out->device_list,
3844 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303845 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003846 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303847 }
3848 } else {
3849 select_devices(adev, out->usecase);
3850 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003851
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003852 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3853 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003854 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003855 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003856
Derek Chenea197282019-01-07 17:35:01 -08003857 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3858 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003859
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003860 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3861 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003862
3863 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003864 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003865 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3866 ALOGE("%s: pcm stream not ready", __func__);
3867 goto error_open;
3868 }
3869 ret = pcm_start(out->pcm);
3870 if (ret < 0) {
3871 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3872 goto error_open;
3873 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003874 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003875 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003876 unsigned int flags = PCM_OUT;
3877 unsigned int pcm_open_retry_count = 0;
3878 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3879 flags |= PCM_MMAP | PCM_NOIRQ;
3880 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003881 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003882 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003883 } else
3884 flags |= PCM_MONOTONIC;
3885
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003886 if ((adev->vr_audio_mode_enabled) &&
3887 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3888 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3889 "PCM_Dev %d Topology", out->pcm_device_id);
3890 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3891 if (!ctl) {
3892 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3893 __func__, mixer_ctl_name);
3894 } else {
3895 //if success use ULLPP
3896 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3897 __func__, mixer_ctl_name, out->pcm_device_id);
3898 //There is a still a possibility that some sessions
3899 // that request for FAST|RAW when 3D audio is active
3900 //can go through ULLPP. Ideally we expects apps to
3901 //listen to audio focus and stop concurrent playback
3902 //Also, we will look for mode flag (voice_in_communication)
3903 //before enabling the realtime flag.
3904 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3905 }
3906 }
3907
Surendar Karka91fa3682018-07-02 18:12:12 +05303908 if (out->realtime)
3909 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3910 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3911
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003912 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3913 flags, pcm_open_retry_count,
3914 &(out->config));
3915 if (out->pcm == NULL) {
3916 ret = -EIO;
3917 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003918 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003919
3920 if (is_haptic_usecase) {
3921 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3922 adev->haptic_pcm_device_id,
3923 flags, pcm_open_retry_count,
3924 &(adev->haptics_config));
3925 // failure to open haptics pcm shouldnt stop audio,
3926 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003927
3928 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3929 ALOGD("%s: enable haptic audio synchronization", __func__);
3930 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3931 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003932 }
3933
Surendar Karka91fa3682018-07-02 18:12:12 +05303934 if (!out->realtime)
3935 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303936 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003937
Zhou Song2b8f28f2017-09-11 10:51:38 +08003938 // apply volume for voip playback after path is set up
3939 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3940 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303941 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3942 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303943 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3944 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003945 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3946 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303947 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003948 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08003949 /*
3950 * set custom channel map if:
3951 * 1. neither mono nor stereo clips i.e. channels > 2 OR
3952 * 2. custom channel map has been set by client
3953 * else default channel map of FC/FR/FL can always be set to DSP
3954 */
3955 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
3956 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3957 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003958 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3959 adev->dsp_bit_width_enforce_mode,
3960 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003962 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003963 out->compr = compress_open(adev->snd_card,
3964 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003965 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003966 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303967 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303968 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3969 adev->card_status = CARD_STATUS_OFFLINE;
3970 out->card_status = CARD_STATUS_OFFLINE;
3971 ret = -EIO;
3972 goto error_open;
3973 }
3974
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003975 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003976 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003977 compress_close(out->compr);
3978 out->compr = NULL;
3979 ret = -EIO;
3980 goto error_open;
3981 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303982 /* compress_open sends params of the track, so reset the flag here */
3983 out->is_compr_metadata_avail = false;
3984
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003985 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003986 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003987
Fred Oh3f43e742015-03-04 18:42:34 -08003988 /* Since small bufs uses blocking writes, a write will be blocked
3989 for the default max poll time (20s) in the event of an SSR.
3990 Reduce the poll time to observe and deal with SSR faster.
3991 */
Ashish Jain5106d362016-05-11 19:23:33 +05303992 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003993 compress_set_max_poll_wait(out->compr, 1000);
3994 }
3995
Manish Dewangan69426c82017-01-30 17:35:36 +05303996 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303997 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303998
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003999 audio_extn_dts_create_state_notifier_node(out->usecase);
4000 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4001 popcount(out->channel_mask),
4002 out->playback_started);
4003
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004004#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304005 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004006 audio_extn_dolby_send_ddp_endp_params(adev);
4007#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304008 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4009 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004010 if (adev->visualizer_start_output != NULL)
4011 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4012 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304013 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004014 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004015 }
Derek Chenf13dd492018-11-13 14:53:51 -08004016
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004017 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004018 /* Update cached volume from media to offload/direct stream */
4019 struct listnode *node = NULL;
4020 list_for_each(node, &adev->active_outputs_list) {
4021 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4022 streams_output_ctxt_t,
4023 list);
4024 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4025 out->volume_l = out_ctxt->output->volume_l;
4026 out->volume_r = out_ctxt->output->volume_r;
4027 }
4028 }
4029 out_set_compr_volume(&out->stream,
4030 out->volume_l, out->volume_r);
4031 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004032 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004033
4034 if (ret == 0) {
4035 register_out_stream(out);
4036 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004037 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4038 ALOGE("%s: pcm stream not ready", __func__);
4039 goto error_open;
4040 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004041 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004042 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004043 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004044 if (ret < 0)
4045 goto error_open;
4046 }
4047 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004048 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304049 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004050 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004051
vivek mehtad15d2bf2019-05-17 13:35:10 -07004052 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4053 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4054 audio_low_latency_hint_start();
4055 }
4056
Manish Dewangan21a850a2017-08-14 12:03:55 +05304057 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004058 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004059 if (ret < 0)
4060 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4061 }
4062
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004063 // consider a scenario where on pause lower layers are tear down.
4064 // so on resume, swap mixer control need to be sent only when
4065 // backend is active, hence rather than sending from enable device
4066 // sending it from start of streamtream
4067
4068 platform_set_swap_channels(adev, true);
4069
Haynes Mathew George380745d2017-10-04 15:27:45 -07004070 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304071 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004072 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004073error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004074 if (adev->haptic_pcm) {
4075 pcm_close(adev->haptic_pcm);
4076 adev->haptic_pcm = NULL;
4077 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004078 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304079 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004080 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004081error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304082 /*
4083 * sleep 50ms to allow sufficient time for kernel
4084 * drivers to recover incases like SSR.
4085 */
4086 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004087error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004088 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304089 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004090 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091}
4092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093static int check_input_parameters(uint32_t sample_rate,
4094 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004095 int channel_count,
4096 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004097{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004098 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004099
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304100 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4101 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4102 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004103 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004104 !audio_extn_compr_cap_format_supported(format) &&
4105 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004106 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004107
Aalique Grahame22e49102018-12-18 14:23:57 -08004108 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4109 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4110 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4111 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4112 return -EINVAL;
4113 }
4114
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004115 switch (channel_count) {
4116 case 1:
4117 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304118 case 3:
4119 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004120 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004121 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304122 case 10:
4123 case 12:
4124 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004125 break;
4126 default:
4127 ret = -EINVAL;
4128 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004129
4130 switch (sample_rate) {
4131 case 8000:
4132 case 11025:
4133 case 12000:
4134 case 16000:
4135 case 22050:
4136 case 24000:
4137 case 32000:
4138 case 44100:
4139 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004140 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304141 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004142 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304143 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144 break;
4145 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004146 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147 }
4148
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004149 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004150}
4151
Naresh Tanniru04f71882018-06-26 17:46:22 +05304152
4153/** Add a value in a list if not already present.
4154 * @return true if value was successfully inserted or already present,
4155 * false if the list is full and does not contain the value.
4156 */
4157static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4158 for (size_t i = 0; i < list_length; i++) {
4159 if (list[i] == value) return true; // value is already present
4160 if (list[i] == 0) { // no values in this slot
4161 list[i] = value;
4162 return true; // value inserted
4163 }
4164 }
4165 return false; // could not insert value
4166}
4167
4168/** Add channel_mask in supported_channel_masks if not already present.
4169 * @return true if channel_mask was successfully inserted or already present,
4170 * false if supported_channel_masks is full and does not contain channel_mask.
4171 */
4172static void register_channel_mask(audio_channel_mask_t channel_mask,
4173 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4174 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4175 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4176}
4177
4178/** Add format in supported_formats if not already present.
4179 * @return true if format was successfully inserted or already present,
4180 * false if supported_formats is full and does not contain format.
4181 */
4182static void register_format(audio_format_t format,
4183 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4184 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4185 "%s: stream can not declare supporting its format %x", __func__, format);
4186}
4187/** Add sample_rate in supported_sample_rates if not already present.
4188 * @return true if sample_rate was successfully inserted or already present,
4189 * false if supported_sample_rates is full and does not contain sample_rate.
4190 */
4191static void register_sample_rate(uint32_t sample_rate,
4192 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4193 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4194 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4195}
4196
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004197static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4198{
4199 uint32_t high = num1, low = num2, temp = 0;
4200
4201 if (!num1 || !num2)
4202 return 0;
4203
4204 if (num1 < num2) {
4205 high = num2;
4206 low = num1;
4207 }
4208
4209 while (low != 0) {
4210 temp = low;
4211 low = high % low;
4212 high = temp;
4213 }
4214 return (num1 * num2)/high;
4215}
4216
4217static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4218{
4219 uint32_t remainder = 0;
4220
4221 if (!multiplier)
4222 return num;
4223
4224 remainder = num % multiplier;
4225 if (remainder)
4226 num += (multiplier - remainder);
4227
4228 return num;
4229}
4230
Aalique Grahame22e49102018-12-18 14:23:57 -08004231static size_t get_stream_buffer_size(size_t duration_ms,
4232 uint32_t sample_rate,
4233 audio_format_t format,
4234 int channel_count,
4235 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236{
4237 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004238 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004239
Aalique Grahame22e49102018-12-18 14:23:57 -08004240 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004241 if (is_low_latency)
4242 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304243
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004244 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004245 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246
Ralf Herzbd08d632018-09-28 15:50:49 +02004247 /* make sure the size is multiple of 32 bytes and additionally multiple of
4248 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004249 * At 48 kHz mono 16-bit PCM:
4250 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4251 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004252 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004253 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004254 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004255
4256 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257}
4258
Aalique Grahame22e49102018-12-18 14:23:57 -08004259static size_t get_input_buffer_size(uint32_t sample_rate,
4260 audio_format_t format,
4261 int channel_count,
4262 bool is_low_latency)
4263{
4264 /* Don't know if USB HIFI in this context so use true to be conservative */
4265 if (check_input_parameters(sample_rate, format, channel_count,
4266 true /*is_usb_hifi */) != 0)
4267 return 0;
4268
4269 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4270 sample_rate,
4271 format,
4272 channel_count,
4273 is_low_latency);
4274}
4275
Derek Chenf6318be2017-06-12 17:16:24 -04004276size_t get_output_period_size(uint32_t sample_rate,
4277 audio_format_t format,
4278 int channel_count,
4279 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304280{
4281 size_t size = 0;
4282 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4283
4284 if ((duration == 0) || (sample_rate == 0) ||
4285 (bytes_per_sample == 0) || (channel_count == 0)) {
4286 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4287 bytes_per_sample, channel_count);
4288 return -EINVAL;
4289 }
4290
4291 size = (sample_rate *
4292 duration *
4293 bytes_per_sample *
4294 channel_count) / 1000;
4295 /*
4296 * To have same PCM samples for all channels, the buffer size requires to
4297 * be multiple of (number of channels * bytes per sample)
4298 * For writes to succeed, the buffer must be written at address which is multiple of 32
4299 */
4300 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4301
4302 return (size/(channel_count * bytes_per_sample));
4303}
4304
Zhou Song48453a02018-01-10 17:50:59 +08004305static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304306{
4307 uint64_t actual_frames_rendered = 0;
4308 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4309
4310 /* This adjustment accounts for buffering after app processor.
4311 * It is based on estimated DSP latency per use case, rather than exact.
4312 */
Robert Lee58215542019-07-15 20:55:12 +08004313 pthread_mutex_lock(&adev->lock);
4314 int64_t platform_latency = platform_render_latency(out->dev, out->usecase) *
Ashish Jain5106d362016-05-11 19:23:33 +05304315 out->sample_rate / 1000000LL;
Robert Lee58215542019-07-15 20:55:12 +08004316 pthread_mutex_unlock(&adev->lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304317
Zhou Song48453a02018-01-10 17:50:59 +08004318 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304319 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4320 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4321 * hence only estimate.
4322 */
George Gao62ebc722019-07-29 16:29:44 -07004323 uint64_t signed_frames = 0;
4324 if (out->written >= kernel_buffer_size)
4325 signed_frames = out->written - kernel_buffer_size;
Ashish Jain5106d362016-05-11 19:23:33 +05304326
George Gao62ebc722019-07-29 16:29:44 -07004327 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask));
4328 if (signed_frames >= platform_latency)
4329 signed_frames = signed_frames - platform_latency;
Ashish Jain5106d362016-05-11 19:23:33 +05304330
Zhou Song48453a02018-01-10 17:50:59 +08004331 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304332 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004333 if (timestamp != NULL )
4334 *timestamp = out->writeAt;
4335 } else if (timestamp != NULL) {
4336 clock_gettime(CLOCK_MONOTONIC, timestamp);
4337 }
4338 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304339
4340 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
George Gao62ebc722019-07-29 16:29:44 -07004341 "bytes/sample %zu channel count %d", __func__, signed_frames,
Ashish Jain5106d362016-05-11 19:23:33 +05304342 (long long int)out->written, (int)kernel_buffer_size,
4343 audio_bytes_per_sample(out->compr_config.codec->format),
4344 popcount(out->channel_mask));
4345
4346 return actual_frames_rendered;
4347}
4348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004349static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4350{
4351 struct stream_out *out = (struct stream_out *)stream;
4352
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004353 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354}
4355
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004356static int out_set_sample_rate(struct audio_stream *stream __unused,
4357 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004358{
4359 return -ENOSYS;
4360}
4361
4362static size_t out_get_buffer_size(const struct audio_stream *stream)
4363{
4364 struct stream_out *out = (struct stream_out *)stream;
4365
Varun Balaraje49253e2017-07-06 19:48:56 +05304366 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304367 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304368 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304369 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4370 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4371 else
4372 return out->compr_config.fragment_size;
4373 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004374 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304375 else if (is_offload_usecase(out->usecase) &&
4376 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304377 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004378
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004379 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004380 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381}
4382
4383static uint32_t out_get_channels(const struct audio_stream *stream)
4384{
4385 struct stream_out *out = (struct stream_out *)stream;
4386
4387 return out->channel_mask;
4388}
4389
4390static audio_format_t out_get_format(const struct audio_stream *stream)
4391{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004392 struct stream_out *out = (struct stream_out *)stream;
4393
4394 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004395}
4396
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004397static int out_set_format(struct audio_stream *stream __unused,
4398 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004399{
4400 return -ENOSYS;
4401}
4402
4403static int out_standby(struct audio_stream *stream)
4404{
4405 struct stream_out *out = (struct stream_out *)stream;
4406 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004407 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004408
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304409 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4410 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004411
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004412 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004413 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004414 if (adev->adm_deregister_stream)
4415 adev->adm_deregister_stream(adev->adm_data, out->handle);
4416
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004417 if (is_offload_usecase(out->usecase))
4418 stop_compressed_output_l(out);
4419
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004420 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004422 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4423 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304424 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004425 pthread_mutex_unlock(&adev->lock);
4426 pthread_mutex_unlock(&out->lock);
4427 ALOGD("VOIP output entered standby");
4428 return 0;
4429 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004430 if (out->pcm) {
4431 pcm_close(out->pcm);
4432 out->pcm = NULL;
4433 }
Meng Wanga09da002020-04-20 12:56:04 +08004434 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4435 if (adev->haptic_pcm) {
4436 pcm_close(adev->haptic_pcm);
4437 adev->haptic_pcm = NULL;
4438 }
4439
4440 if (adev->haptic_buffer != NULL) {
4441 free(adev->haptic_buffer);
4442 adev->haptic_buffer = NULL;
4443 adev->haptic_buffer_size = 0;
4444 }
4445 adev->haptic_pcm_device_id = 0;
4446 }
4447
Haynes Mathew George16081042017-05-31 17:16:49 -07004448 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4449 do_stop = out->playback_started;
4450 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004451
4452 if (out->mmap_shared_memory_fd >= 0) {
4453 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4454 __func__, out->mmap_shared_memory_fd);
4455 close(out->mmap_shared_memory_fd);
4456 out->mmap_shared_memory_fd = -1;
4457 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004458 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004459 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004460 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304461 out->send_next_track_params = false;
4462 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004463 out->gapless_mdata.encoder_delay = 0;
4464 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004465 if (out->compr != NULL) {
4466 compress_close(out->compr);
4467 out->compr = NULL;
4468 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004469 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004470 if (do_stop) {
4471 stop_output_stream(out);
4472 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304473 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004474 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004475 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004476 }
4477 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304478 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004479 return 0;
4480}
4481
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304482static int out_on_error(struct audio_stream *stream)
4483{
4484 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004485 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304486
4487 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004488 // always send CMD_ERROR for offload streams, this
4489 // is needed e.g. when SSR happens within compress_open
4490 // since the stream is active, offload_callback_thread is also active.
4491 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4492 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004493 }
4494 pthread_mutex_unlock(&out->lock);
4495
4496 status = out_standby(&out->stream.common);
4497
4498 lock_output_stream(out);
4499 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004500 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304501 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304502
4503 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4504 ALOGD("Setting previous card status if offline");
4505 out->prev_card_status_offline = true;
4506 }
4507
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304508 pthread_mutex_unlock(&out->lock);
4509
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004510 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304511}
4512
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304513/*
4514 *standby implementation without locks, assumes that the callee already
4515 *has taken adev and out lock.
4516 */
4517int out_standby_l(struct audio_stream *stream)
4518{
4519 struct stream_out *out = (struct stream_out *)stream;
4520 struct audio_device *adev = out->dev;
4521
4522 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4523 stream, out->usecase, use_case_table[out->usecase]);
4524
4525 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004526 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304527 if (adev->adm_deregister_stream)
4528 adev->adm_deregister_stream(adev->adm_data, out->handle);
4529
4530 if (is_offload_usecase(out->usecase))
4531 stop_compressed_output_l(out);
4532
4533 out->standby = true;
4534 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4535 voice_extn_compress_voip_close_output_stream(stream);
4536 out->started = 0;
4537 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004538 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304539 return 0;
4540 } else if (!is_offload_usecase(out->usecase)) {
4541 if (out->pcm) {
4542 pcm_close(out->pcm);
4543 out->pcm = NULL;
4544 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004545 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4546 if (adev->haptic_pcm) {
4547 pcm_close(adev->haptic_pcm);
4548 adev->haptic_pcm = NULL;
4549 }
4550
4551 if (adev->haptic_buffer != NULL) {
4552 free(adev->haptic_buffer);
4553 adev->haptic_buffer = NULL;
4554 adev->haptic_buffer_size = 0;
4555 }
4556 adev->haptic_pcm_device_id = 0;
4557 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304558 } else {
4559 ALOGD("copl(%p):standby", out);
4560 out->send_next_track_params = false;
4561 out->is_compr_metadata_avail = false;
4562 out->gapless_mdata.encoder_delay = 0;
4563 out->gapless_mdata.encoder_padding = 0;
4564 if (out->compr != NULL) {
4565 compress_close(out->compr);
4566 out->compr = NULL;
4567 }
4568 }
4569 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004570 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304571 }
4572 ALOGD("%s: exit", __func__);
4573 return 0;
4574}
4575
Aalique Grahame22e49102018-12-18 14:23:57 -08004576static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577{
Aalique Grahame22e49102018-12-18 14:23:57 -08004578 struct stream_out *out = (struct stream_out *)stream;
4579
4580 // We try to get the lock for consistency,
4581 // but it isn't necessary for these variables.
4582 // If we're not in standby, we may be blocked on a write.
4583 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4584 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4585 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4586
Andy Hunga1f48fa2019-07-01 18:14:53 -07004587 char buffer[256]; // for statistics formatting
4588 if (!is_offload_usecase(out->usecase)) {
4589 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4590 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4591 }
4592
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004593 if (out->start_latency_ms.n > 0) {
4594 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4595 dprintf(fd, " Start latency ms: %s\n", buffer);
4596 }
4597
Aalique Grahame22e49102018-12-18 14:23:57 -08004598 if (locked) {
4599 pthread_mutex_unlock(&out->lock);
4600 }
4601
4602 // dump error info
4603 (void)error_log_dump(
4604 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606 return 0;
4607}
4608
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004609static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4610{
4611 int ret = 0;
4612 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004613
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004614 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004615 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004616 return -EINVAL;
4617 }
4618
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304619 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004620
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004621 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4622 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304623 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004624 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004625 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4626 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304627 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004628 }
4629
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004630 ALOGV("%s new encoder delay %u and padding %u", __func__,
4631 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4632
4633 return 0;
4634}
4635
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004636static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4637{
4638 return out == adev->primary_output || out == adev->voice_tx_output;
4639}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004640
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304641// note: this call is safe only if the stream_cb is
4642// removed first in close_output_stream (as is done now).
4643static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4644{
4645 if (!stream || !parms)
4646 return;
4647
4648 struct stream_out *out = (struct stream_out *)stream;
4649 struct audio_device *adev = out->dev;
4650
4651 card_status_t status;
4652 int card;
4653 if (parse_snd_card_status(parms, &card, &status) < 0)
4654 return;
4655
4656 pthread_mutex_lock(&adev->lock);
4657 bool valid_cb = (card == adev->snd_card);
4658 pthread_mutex_unlock(&adev->lock);
4659
4660 if (!valid_cb)
4661 return;
4662
4663 lock_output_stream(out);
4664 if (out->card_status != status)
4665 out->card_status = status;
4666 pthread_mutex_unlock(&out->lock);
4667
4668 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4669 use_case_table[out->usecase],
4670 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4671
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304672 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304673 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304674 if (voice_is_call_state_active(adev) &&
4675 out == adev->primary_output) {
4676 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4677 pthread_mutex_lock(&adev->lock);
4678 voice_stop_call(adev);
4679 adev->mode = AUDIO_MODE_NORMAL;
4680 pthread_mutex_unlock(&adev->lock);
4681 }
4682 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304683 return;
4684}
4685
Kevin Rocardfce19002017-08-07 19:21:36 -07004686static int get_alive_usb_card(struct str_parms* parms) {
4687 int card;
4688 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4689 !audio_extn_usb_alive(card)) {
4690 return card;
4691 }
4692 return -ENODEV;
4693}
4694
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004695int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004696 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004697{
4698 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004699 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004700 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004701 bool bypass_a2dp = false;
4702 bool reconfig = false;
4703 unsigned long service_interval = 0;
4704
4705 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004706 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4707
4708 list_init(&new_devices);
4709 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004710
4711 lock_output_stream(out);
4712 pthread_mutex_lock(&adev->lock);
4713
4714 /*
4715 * When HDMI cable is unplugged the music playback is paused and
4716 * the policy manager sends routing=0. But the audioflinger continues
4717 * to write data until standby time (3sec). As the HDMI core is
4718 * turned off, the write gets blocked.
4719 * Avoid this by routing audio to speaker until standby.
4720 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004721 if (is_single_device_type_equal(&out->device_list,
4722 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004723 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004724 !audio_extn_passthru_is_passthrough_stream(out) &&
4725 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004726 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004727 }
4728 /*
4729 * When A2DP is disconnected the
4730 * music playback is paused and the policy manager sends routing=0
4731 * But the audioflinger continues to write data until standby time
4732 * (3sec). As BT is turned off, the write gets blocked.
4733 * Avoid this by routing audio to speaker until standby.
4734 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004735 if (is_a2dp_out_device_type(&out->device_list) &&
4736 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004737 !audio_extn_a2dp_source_is_ready() &&
4738 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004739 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004740 }
4741 /*
4742 * When USB headset is disconnected the music platback paused
4743 * and the policy manager send routing=0. But if the USB is connected
4744 * back before the standby time, AFE is not closed and opened
4745 * when USB is connected back. So routing to speker will guarantee
4746 * AFE reconfiguration and AFE will be opend once USB is connected again
4747 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004748 if (is_usb_out_device_type(&out->device_list) &&
4749 list_empty(&new_devices) &&
4750 !audio_extn_usb_connected(NULL)) {
4751 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4752 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004753 /* To avoid a2dp to sco overlapping / BT device improper state
4754 * check with BT lib about a2dp streaming support before routing
4755 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004756 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004757 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004758 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4759 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004760 //combo usecase just by pass a2dp
4761 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4762 bypass_a2dp = true;
4763 } else {
4764 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4765 /* update device to a2dp and don't route as BT returned error
4766 * However it is still possible a2dp routing called because
4767 * of current active device disconnection (like wired headset)
4768 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004769 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004770 pthread_mutex_unlock(&adev->lock);
4771 pthread_mutex_unlock(&out->lock);
4772 goto error;
4773 }
4774 }
4775 }
4776
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004777 // Workaround: If routing to an non existing usb device, fail gracefully
4778 // The routing request will otherwise block during 10 second
4779 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004780 if (is_usb_out_device_type(&new_devices)) {
4781 struct str_parms *parms =
4782 str_parms_create_str(get_usb_device_address(&new_devices));
4783 if (!parms)
4784 goto error;
4785 if ((card = get_alive_usb_card(parms)) >= 0) {
4786 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4787 pthread_mutex_unlock(&adev->lock);
4788 pthread_mutex_unlock(&out->lock);
4789 str_parms_destroy(parms);
4790 ret = -ENOSYS;
4791 goto error;
4792 }
4793 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004794 }
4795
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004796 // Workaround: If routing to an non existing hdmi device, fail gracefully
4797 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4798 (platform_get_edid_info_v2(adev->platform,
4799 out->extconn.cs.controller,
4800 out->extconn.cs.stream) != 0)) {
4801 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4802 pthread_mutex_unlock(&adev->lock);
4803 pthread_mutex_unlock(&out->lock);
4804 ret = -ENOSYS;
4805 goto error;
4806 }
4807
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004808 /*
4809 * select_devices() call below switches all the usecases on the same
4810 * backend to the new device. Refer to check_usecases_codec_backend() in
4811 * the select_devices(). But how do we undo this?
4812 *
4813 * For example, music playback is active on headset (deep-buffer usecase)
4814 * and if we go to ringtones and select a ringtone, low-latency usecase
4815 * will be started on headset+speaker. As we can't enable headset+speaker
4816 * and headset devices at the same time, select_devices() switches the music
4817 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4818 * So when the ringtone playback is completed, how do we undo the same?
4819 *
4820 * We are relying on the out_set_parameters() call on deep-buffer output,
4821 * once the ringtone playback is ended.
4822 * NOTE: We should not check if the current devices are same as new devices.
4823 * Because select_devices() must be called to switch back the music
4824 * playback to headset.
4825 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004826 if (!list_empty(&new_devices)) {
4827 bool same_dev = compare_devices(&out->device_list, &new_devices);
4828 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004829
4830 if (output_drives_call(adev, out)) {
4831 if (!voice_is_call_state_active(adev)) {
4832 if (adev->mode == AUDIO_MODE_IN_CALL) {
4833 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004834 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004835 service_interval =
4836 audio_extn_usb_find_service_interval(true, true /*playback*/);
4837 audio_extn_usb_set_service_interval(true /*playback*/,
4838 service_interval,
4839 &reconfig);
4840 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4841 }
4842 ret = voice_start_call(adev);
4843 }
4844 } else {
4845 adev->current_call_output = out;
4846 voice_update_devices_for_all_voice_usecases(adev);
4847 }
4848 }
4849
4850 if (!out->standby) {
4851 if (!same_dev) {
4852 ALOGV("update routing change");
4853 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4854 adev->perf_lock_opts,
4855 adev->perf_lock_opts_size);
4856 if (adev->adm_on_routing_change)
4857 adev->adm_on_routing_change(adev->adm_data,
4858 out->handle);
4859 }
4860 if (!bypass_a2dp) {
4861 select_devices(adev, out->usecase);
4862 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004863 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4864 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004865 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004866 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004867 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004868 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004869 }
4870
4871 if (!same_dev) {
4872 // on device switch force swap, lower functions will make sure
4873 // to check if swap is allowed or not.
4874 platform_set_swap_channels(adev, true);
4875 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4876 }
4877 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4878 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004879 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004880 pthread_mutex_lock(&out->compr_mute_lock);
4881 out->a2dp_compress_mute = false;
4882 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4883 pthread_mutex_unlock(&out->compr_mute_lock);
4884 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4885 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4886 }
4887 }
4888 }
4889
4890 pthread_mutex_unlock(&adev->lock);
4891 pthread_mutex_unlock(&out->lock);
4892
4893 /*handles device and call state changes*/
4894 audio_extn_extspk_update(adev->extspk);
4895
4896error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004897 ALOGV("%s: exit: code(%d)", __func__, ret);
4898 return ret;
4899}
4900
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004901static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4902{
4903 struct stream_out *out = (struct stream_out *)stream;
4904 struct audio_device *adev = out->dev;
4905 struct str_parms *parms;
4906 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004907 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004908 int ext_controller = -1;
4909 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004910
sangwoobc677242013-08-08 16:53:43 +09004911 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004912 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004913 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304914 if (!parms)
4915 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004916
4917 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4918 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08004919 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004920 out->extconn.cs.controller = ext_controller;
4921 out->extconn.cs.stream = ext_stream;
4922 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4923 use_case_table[out->usecase], out->extconn.cs.controller,
4924 out->extconn.cs.stream);
4925 }
4926
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004927 if (out == adev->primary_output) {
4928 pthread_mutex_lock(&adev->lock);
4929 audio_extn_set_parameters(adev, parms);
4930 pthread_mutex_unlock(&adev->lock);
4931 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004932 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004933 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004934 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004935
4936 audio_extn_dts_create_state_notifier_node(out->usecase);
4937 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4938 popcount(out->channel_mask),
4939 out->playback_started);
4940
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004941 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004942 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004943
Surendar Karkaf51b5842018-04-26 11:28:38 +05304944 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4945 sizeof(value));
4946 if (err >= 0) {
4947 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4948 audio_extn_send_dual_mono_mixing_coefficients(out);
4949 }
4950
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304951 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4952 if (err >= 0) {
4953 strlcpy(out->profile, value, sizeof(out->profile));
4954 ALOGV("updating stream profile with value '%s'", out->profile);
4955 lock_output_stream(out);
4956 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4957 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004958 &out->device_list, out->flags,
4959 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304960 out->sample_rate, out->bit_width,
4961 out->channel_mask, out->profile,
4962 &out->app_type_cfg);
4963 pthread_mutex_unlock(&out->lock);
4964 }
4965
Alexy Joseph98988832017-01-13 14:56:59 -08004966 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004967 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4968 // and vendor.audio.hal.output.suspend.supported is set to true
4969 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004970 //check suspend parameter only for low latency and if the property
4971 //is enabled
4972 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4973 ALOGI("%s: got suspend_playback %s", __func__, value);
4974 lock_output_stream(out);
4975 if (!strncmp(value, "false", 5)) {
4976 //suspend_playback=false is supposed to set QOS value back to 75%
4977 //the mixer control sent with value Enable will achieve that
4978 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4979 } else if (!strncmp (value, "true", 4)) {
4980 //suspend_playback=true is supposed to remove QOS value
4981 //resetting the mixer control will set the default value
4982 //for the mixer control which is Disable and this removes the QOS vote
4983 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4984 } else {
4985 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4986 " got %s", __func__, value);
4987 ret = -1;
4988 }
4989
4990 if (ret != 0) {
4991 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4992 __func__, out->pm_qos_mixer_path, ret);
4993 }
4994
4995 pthread_mutex_unlock(&out->lock);
4996 }
4997 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004998
Alexy Joseph98988832017-01-13 14:56:59 -08004999 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005000 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305001error:
Eric Laurent994a6932013-07-17 11:51:42 -07005002 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005003 return ret;
5004}
5005
Paul McLeana50b7332018-12-17 08:24:21 -07005006static int in_set_microphone_direction(const struct audio_stream_in *stream,
5007 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005008 struct stream_in *in = (struct stream_in *)stream;
5009
5010 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5011
5012 in->direction = dir;
5013
5014 if (in->standby)
5015 return 0;
5016
5017 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005018}
5019
5020static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005021 struct stream_in *in = (struct stream_in *)stream;
5022
5023 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5024
5025 if (zoom > 1.0 || zoom < -1.0)
5026 return -EINVAL;
5027
5028 in->zoom = zoom;
5029
5030 if (in->standby)
5031 return 0;
5032
5033 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005034}
5035
5036
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005037static bool stream_get_parameter_channels(struct str_parms *query,
5038 struct str_parms *reply,
5039 audio_channel_mask_t *supported_channel_masks) {
5040 int ret = -1;
5041 char value[512];
5042 bool first = true;
5043 size_t i, j;
5044
5045 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5046 ret = 0;
5047 value[0] = '\0';
5048 i = 0;
5049 while (supported_channel_masks[i] != 0) {
5050 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5051 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5052 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305053 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005054
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305055 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005056 first = false;
5057 break;
5058 }
5059 }
5060 i++;
5061 }
5062 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5063 }
5064 return ret == 0;
5065}
5066
5067static bool stream_get_parameter_formats(struct str_parms *query,
5068 struct str_parms *reply,
5069 audio_format_t *supported_formats) {
5070 int ret = -1;
5071 char value[256];
5072 size_t i, j;
5073 bool first = true;
5074
5075 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5076 ret = 0;
5077 value[0] = '\0';
5078 i = 0;
5079 while (supported_formats[i] != 0) {
5080 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5081 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5082 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305083 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005084 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305085 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005086 first = false;
5087 break;
5088 }
5089 }
5090 i++;
5091 }
5092 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5093 }
5094 return ret == 0;
5095}
5096
5097static bool stream_get_parameter_rates(struct str_parms *query,
5098 struct str_parms *reply,
5099 uint32_t *supported_sample_rates) {
5100
5101 int i;
5102 char value[256];
5103 int ret = -1;
5104 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5105 ret = 0;
5106 value[0] = '\0';
5107 i=0;
5108 int cursor = 0;
5109 while (supported_sample_rates[i]) {
5110 int avail = sizeof(value) - cursor;
5111 ret = snprintf(value + cursor, avail, "%s%d",
5112 cursor > 0 ? "|" : "",
5113 supported_sample_rates[i]);
5114 if (ret < 0 || ret >= avail) {
5115 // if cursor is at the last element of the array
5116 // overwrite with \0 is duplicate work as
5117 // snprintf already put a \0 in place.
5118 // else
5119 // we had space to write the '|' at value[cursor]
5120 // (which will be overwritten) or no space to fill
5121 // the first element (=> cursor == 0)
5122 value[cursor] = '\0';
5123 break;
5124 }
5125 cursor += ret;
5126 ++i;
5127 }
5128 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5129 value);
5130 }
5131 return ret >= 0;
5132}
5133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005134static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5135{
5136 struct stream_out *out = (struct stream_out *)stream;
5137 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005138 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005139 char value[256];
5140 struct str_parms *reply = str_parms_create();
5141 size_t i, j;
5142 int ret;
5143 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005144
5145 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005146 if (reply) {
5147 str_parms_destroy(reply);
5148 }
5149 if (query) {
5150 str_parms_destroy(query);
5151 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005152 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5153 return NULL;
5154 }
5155
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005156 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005157 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5158 if (ret >= 0) {
5159 value[0] = '\0';
5160 i = 0;
5161 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005162 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5163 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005164 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005165 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005166 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005167 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005168 first = false;
5169 break;
5170 }
5171 }
5172 i++;
5173 }
5174 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5175 str = str_parms_to_str(reply);
5176 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005177 voice_extn_out_get_parameters(out, query, reply);
5178 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005179 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005180
Alexy Joseph62142aa2015-11-16 15:10:34 -08005181
5182 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5183 if (ret >= 0) {
5184 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305185 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5186 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005187 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305188 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005189 } else {
5190 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305191 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005192 }
5193 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005194 if (str)
5195 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005196 str = str_parms_to_str(reply);
5197 }
5198
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005199 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5200 if (ret >= 0) {
5201 value[0] = '\0';
5202 i = 0;
5203 first = true;
5204 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005205 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5206 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005207 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005208 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005209 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005210 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005211 first = false;
5212 break;
5213 }
5214 }
5215 i++;
5216 }
5217 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005218 if (str)
5219 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005220 str = str_parms_to_str(reply);
5221 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005222
5223 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5224 if (ret >= 0) {
5225 value[0] = '\0';
5226 i = 0;
5227 first = true;
5228 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005229 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5230 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005231 if (!first) {
5232 strlcat(value, "|", sizeof(value));
5233 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005234 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005235 first = false;
5236 break;
5237 }
5238 }
5239 i++;
5240 }
5241 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5242 if (str)
5243 free(str);
5244 str = str_parms_to_str(reply);
5245 }
5246
Alexy Joseph98988832017-01-13 14:56:59 -08005247 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5248 //only low latency track supports suspend_resume
5249 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005250 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005251 if (str)
5252 free(str);
5253 str = str_parms_to_str(reply);
5254 }
5255
5256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005257 str_parms_destroy(query);
5258 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005259 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005260 return str;
5261}
5262
5263static uint32_t out_get_latency(const struct audio_stream_out *stream)
5264{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005265 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005266 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005267 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005268
Alexy Josephaa54c872014-12-03 02:46:47 -08005269 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305270 lock_output_stream(out);
5271 latency = audio_extn_utils_compress_get_dsp_latency(out);
5272 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005273 } else if ((out->realtime) ||
5274 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005275 // since the buffer won't be filled up faster than realtime,
5276 // return a smaller number
5277 if (out->config.rate)
5278 period_ms = (out->af_period_multiplier * out->config.period_size *
5279 1000) / (out->config.rate);
5280 else
5281 period_ms = 0;
Robert Lee58215542019-07-15 20:55:12 +08005282 pthread_mutex_lock(&adev->lock);
5283 latency = period_ms + platform_render_latency(out->dev, out->usecase)/1000;
5284 pthread_mutex_unlock(&adev->lock);
Alexy Josephaa54c872014-12-03 02:46:47 -08005285 } else {
5286 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005287 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005288 }
5289
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005290 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005291 latency += audio_extn_a2dp_get_encoder_latency();
5292
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305293 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005294 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005295}
5296
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305297static float AmpToDb(float amplification)
5298{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305299 float db = DSD_VOLUME_MIN_DB;
5300 if (amplification > 0) {
5301 db = 20 * log10(amplification);
5302 if(db < DSD_VOLUME_MIN_DB)
5303 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305304 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305305 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305306}
5307
Arun Mirpuri5d170872019-03-26 13:21:31 -07005308static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5309 float right)
5310{
5311 struct stream_out *out = (struct stream_out *)stream;
5312 long volume = 0;
5313 char mixer_ctl_name[128] = "";
5314 struct audio_device *adev = out->dev;
5315 struct mixer_ctl *ctl = NULL;
5316 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5317 PCM_PLAYBACK);
5318
5319 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5320 "Playback %d Volume", pcm_device_id);
5321 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5322 if (!ctl) {
5323 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5324 __func__, mixer_ctl_name);
5325 return -EINVAL;
5326 }
5327 if (left != right)
5328 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5329 __func__, left, right);
5330 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5331 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5332 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5333 __func__, mixer_ctl_name, volume);
5334 return -EINVAL;
5335 }
5336 return 0;
5337}
5338
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305339static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5340 float right)
5341{
5342 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305343 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305344 char mixer_ctl_name[128];
5345 struct audio_device *adev = out->dev;
5346 struct mixer_ctl *ctl;
5347 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5348 PCM_PLAYBACK);
5349
5350 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5351 "Compress Playback %d Volume", pcm_device_id);
5352 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5353 if (!ctl) {
5354 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5355 __func__, mixer_ctl_name);
5356 return -EINVAL;
5357 }
5358 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5359 __func__, mixer_ctl_name, left, right);
5360 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5361 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5362 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5363
5364 return 0;
5365}
5366
Zhou Song2b8f28f2017-09-11 10:51:38 +08005367static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5368 float right)
5369{
5370 struct stream_out *out = (struct stream_out *)stream;
5371 char mixer_ctl_name[] = "App Type Gain";
5372 struct audio_device *adev = out->dev;
5373 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305374 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005375
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005376 if (!is_valid_volume(left, right)) {
5377 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5378 __func__, left, right);
5379 return -EINVAL;
5380 }
5381
Zhou Song2b8f28f2017-09-11 10:51:38 +08005382 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5383 if (!ctl) {
5384 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5385 __func__, mixer_ctl_name);
5386 return -EINVAL;
5387 }
5388
5389 set_values[0] = 0; //0: Rx Session 1:Tx Session
5390 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305391 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5392 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005393
5394 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5395 return 0;
5396}
5397
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305398static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5399 float right)
5400{
5401 struct stream_out *out = (struct stream_out *)stream;
5402 /* Volume control for pcm playback */
5403 if (left != right) {
5404 return -EINVAL;
5405 } else {
5406 char mixer_ctl_name[128];
5407 struct audio_device *adev = out->dev;
5408 struct mixer_ctl *ctl;
5409 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5410 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5411 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5412 if (!ctl) {
5413 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5414 return -EINVAL;
5415 }
5416
5417 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5418 int ret = mixer_ctl_set_value(ctl, 0, volume);
5419 if (ret < 0) {
5420 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5421 return -EINVAL;
5422 }
5423
5424 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5425
5426 return 0;
5427 }
5428}
5429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005430static int out_set_volume(struct audio_stream_out *stream, float left,
5431 float right)
5432{
Eric Laurenta9024de2013-04-04 09:19:12 -07005433 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005434 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305435 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005436
Arun Mirpuri5d170872019-03-26 13:21:31 -07005437 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005438 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5439 /* only take left channel into account: the API is for stereo anyway */
5440 out->muted = (left == 0.0f);
5441 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005442 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305443 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005444 /*
5445 * Set mute or umute on HDMI passthrough stream.
5446 * Only take left channel into account.
5447 * Mute is 0 and unmute 1
5448 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305449 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305450 } else if (out->format == AUDIO_FORMAT_DSD){
5451 char mixer_ctl_name[128] = "DSD Volume";
5452 struct audio_device *adev = out->dev;
5453 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5454
5455 if (!ctl) {
5456 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5457 __func__, mixer_ctl_name);
5458 return -EINVAL;
5459 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305460 volume[0] = (long)(AmpToDb(left));
5461 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305462 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5463 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005464 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005465 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005466 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5467 struct listnode *node = NULL;
5468 list_for_each(node, &adev->active_outputs_list) {
5469 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5470 streams_output_ctxt_t,
5471 list);
5472 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5473 out->volume_l = out_ctxt->output->volume_l;
5474 out->volume_r = out_ctxt->output->volume_r;
5475 }
5476 }
5477 if (!out->a2dp_compress_mute) {
5478 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5479 }
5480 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005481 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305482 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005483 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305484 if (!out->a2dp_compress_mute)
5485 ret = out_set_compr_volume(stream, left, right);
5486 out->volume_l = left;
5487 out->volume_r = right;
5488 pthread_mutex_unlock(&out->compr_mute_lock);
5489 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005490 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005491 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005492 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5493 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5494 if (!out->standby) {
5495 audio_extn_utils_send_app_type_gain(out->dev,
5496 out->app_type_cfg.app_type,
5497 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005498 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005499 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005500 out->volume_l = left;
5501 out->volume_r = right;
5502 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005503 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5504 ALOGV("%s: MMAP set volume called", __func__);
5505 if (!out->standby)
5506 ret = out_set_mmap_volume(stream, left, right);
5507 out->volume_l = left;
5508 out->volume_r = right;
5509 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305510 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305511 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5512 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305513 /* Volume control for pcm playback */
5514 if (!out->standby)
5515 ret = out_set_pcm_volume(stream, left, right);
5516 else
5517 out->apply_volume = true;
5518
5519 out->volume_l = left;
5520 out->volume_r = right;
5521 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005522 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5523 ALOGV("%s: bus device set volume called", __func__);
5524 if (!out->standby)
5525 ret = out_set_pcm_volume(stream, left, right);
5526 out->volume_l = left;
5527 out->volume_r = right;
5528 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005529 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005531 return -ENOSYS;
5532}
5533
Zhou Songc9672822017-08-16 16:01:39 +08005534static void update_frames_written(struct stream_out *out, size_t bytes)
5535{
5536 size_t bpf = 0;
5537
5538 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5539 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5540 bpf = 1;
5541 else if (!is_offload_usecase(out->usecase))
5542 bpf = audio_bytes_per_sample(out->format) *
5543 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005544
5545 pthread_mutex_lock(&out->position_query_lock);
5546 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005547 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005548 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5549 }
5550 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005551}
5552
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005553int split_and_write_audio_haptic_data(struct stream_out *out,
5554 const void *buffer, size_t bytes_to_write)
5555{
5556 struct audio_device *adev = out->dev;
5557
5558 int ret = 0;
5559 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5560 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5561 size_t frame_size = channel_count * bytes_per_sample;
5562 size_t frame_count = bytes_to_write / frame_size;
5563
5564 bool force_haptic_path =
5565 property_get_bool("vendor.audio.test_haptic", false);
5566
5567 // extract Haptics data from Audio buffer
5568 bool alloc_haptic_buffer = false;
5569 int haptic_channel_count = adev->haptics_config.channels;
5570 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5571 size_t audio_frame_size = frame_size - haptic_frame_size;
5572 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5573
5574 if (adev->haptic_buffer == NULL) {
5575 alloc_haptic_buffer = true;
5576 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5577 free(adev->haptic_buffer);
5578 adev->haptic_buffer_size = 0;
5579 alloc_haptic_buffer = true;
5580 }
5581
5582 if (alloc_haptic_buffer) {
5583 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005584 if(adev->haptic_buffer == NULL) {
5585 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5586 return -ENOMEM;
5587 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005588 adev->haptic_buffer_size = total_haptic_buffer_size;
5589 }
5590
5591 size_t src_index = 0, aud_index = 0, hap_index = 0;
5592 uint8_t *audio_buffer = (uint8_t *)buffer;
5593 uint8_t *haptic_buffer = adev->haptic_buffer;
5594
5595 // This is required for testing only. This works for stereo data only.
5596 // One channel is fed to audio stream and other to haptic stream for testing.
5597 if (force_haptic_path)
5598 audio_frame_size = haptic_frame_size = bytes_per_sample;
5599
5600 for (size_t i = 0; i < frame_count; i++) {
5601 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5602 audio_frame_size);
5603 aud_index += audio_frame_size;
5604 src_index += audio_frame_size;
5605
5606 if (adev->haptic_pcm)
5607 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5608 haptic_frame_size);
5609 hap_index += haptic_frame_size;
5610 src_index += haptic_frame_size;
5611
5612 // This is required for testing only.
5613 // Discard haptic channel data.
5614 if (force_haptic_path)
5615 src_index += haptic_frame_size;
5616 }
5617
5618 // write to audio pipeline
5619 ret = pcm_write(out->pcm, (void *)audio_buffer,
5620 frame_count * audio_frame_size);
5621
5622 // write to haptics pipeline
5623 if (adev->haptic_pcm)
5624 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5625 frame_count * haptic_frame_size);
5626
5627 return ret;
5628}
5629
Aalique Grahame22e49102018-12-18 14:23:57 -08005630#ifdef NO_AUDIO_OUT
5631static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5632 const void *buffer __unused, size_t bytes)
5633{
5634 struct stream_out *out = (struct stream_out *)stream;
5635
5636 /* No Output device supported other than BT for playback.
5637 * Sleep for the amount of buffer duration
5638 */
5639 lock_output_stream(out);
5640 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5641 (const struct audio_stream_out *)&out->stream) /
5642 out_get_sample_rate(&out->stream.common));
5643 pthread_mutex_unlock(&out->lock);
5644 return bytes;
5645}
5646#endif
5647
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005648static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5649 size_t bytes)
5650{
5651 struct stream_out *out = (struct stream_out *)stream;
5652 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005653 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305654 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005655 const size_t frame_size = audio_stream_out_frame_size(stream);
5656 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305657 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005658 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005659
Haynes Mathew George380745d2017-10-04 15:27:45 -07005660 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005661 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305662
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305663 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005664
Dhananjay Kumarac341582017-02-23 23:42:25 +05305665 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305666 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305667 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5668 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005669 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305670 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305671 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305672 ALOGD(" %s: sound card is not active/SSR state", __func__);
5673 ret= -EIO;
5674 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305675 }
5676 }
5677
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305678 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305679 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305680 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305681 goto exit;
5682 }
5683
Haynes Mathew George16081042017-05-31 17:16:49 -07005684 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5685 ret = -EINVAL;
5686 goto exit;
5687 }
5688
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005689 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305690 !out->is_iec61937_info_available) {
5691
5692 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5693 out->is_iec61937_info_available = true;
5694 } else if (audio_extn_passthru_is_enabled()) {
5695 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305696 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305697
5698 if((out->format == AUDIO_FORMAT_DTS) ||
5699 (out->format == AUDIO_FORMAT_DTS_HD)) {
5700 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5701 buffer, bytes);
5702 if (ret) {
5703 if (ret != -ENOSYS) {
5704 out->is_iec61937_info_available = false;
5705 ALOGD("iec61937 transmission info not yet updated retry");
5706 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305707 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305708 /* if stream has started and after that there is
5709 * stream config change (iec transmission config)
5710 * then trigger select_device to update backend configuration.
5711 */
5712 out->stream_config_changed = true;
5713 pthread_mutex_lock(&adev->lock);
5714 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305715 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005716 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305717 ret = -EINVAL;
5718 goto exit;
5719 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305720 pthread_mutex_unlock(&adev->lock);
5721 out->stream_config_changed = false;
5722 out->is_iec61937_info_available = true;
5723 }
5724 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305725
Meng Wang4c32fb42020-01-16 17:57:11 +08005726#ifdef AUDIO_GKI_ENABLED
5727 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5728 compr_passthr = out->compr_config.codec->reserved[0];
5729#else
5730 compr_passthr = out->compr_config.codec->compr_passthr;
5731#endif
5732
Garmond Leung317cbf12017-09-13 16:20:50 -07005733 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005734 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305735 (out->is_iec61937_info_available == true)) {
5736 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5737 ret = -EINVAL;
5738 goto exit;
5739 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305740 }
5741 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305742
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005743 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005744 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005745 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5746 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305747 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305748 ret = -EIO;
5749 goto exit;
5750 }
5751 }
5752 }
5753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005754 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005755 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005756 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5757
Eric Laurent150dbfe2013-02-27 14:31:02 -08005758 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005759 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5760 ret = voice_extn_compress_voip_start_output_stream(out);
5761 else
5762 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005763 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005764 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005765 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005766 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005767 goto exit;
5768 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305769 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005770 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
vivek mehtab72d08d2016-04-29 03:16:47 -07005771 if (last_known_cal_step != -1) {
5772 ALOGD("%s: retry previous failed cal level set", __func__);
5773 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305774 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005775 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305776
5777 if ((out->is_iec61937_info_available == true) &&
5778 (audio_extn_passthru_is_passthrough_stream(out))&&
5779 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5780 ret = -EINVAL;
5781 goto exit;
5782 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305783 if (out->set_dual_mono)
5784 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005785
5786 // log startup time in ms.
5787 simple_stats_log(
5788 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005789 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005790
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005791 if (adev->is_channel_status_set == false &&
5792 compare_device_type(&out->device_list,
5793 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005794 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305795 adev->is_channel_status_set = true;
5796 }
5797
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305798 if ((adev->use_old_pspd_mix_ctrl == true) &&
5799 (out->pspd_coeff_sent == false)) {
5800 /*
5801 * Need to resend pspd coefficients after stream started for
5802 * older kernel version as it does not save the coefficients
5803 * and also stream has to be started for coeff to apply.
5804 */
5805 usecase = get_usecase_from_list(adev, out->usecase);
5806 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305807 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305808 out->pspd_coeff_sent = true;
5809 }
5810 }
5811
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005812 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005813 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005814 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005815 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005816 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5817 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305818 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5819 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005820 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305821 out->send_next_track_params = false;
5822 out->is_compr_metadata_avail = false;
5823 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005824 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305825 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305826 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005827
Ashish Jain83a6cc22016-06-28 14:34:17 +05305828 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305829 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305830 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305831 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005832 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305833 return -EINVAL;
5834 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305835 audio_format_t dst_format = out->hal_op_format;
5836 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305837
Dieter Luecking5d57def2018-09-07 14:23:37 +02005838 /* prevent division-by-zero */
5839 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5840 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5841 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5842 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305843 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005844 ATRACE_END();
5845 return -EINVAL;
5846 }
5847
Ashish Jainf1eaa582016-05-23 20:54:24 +05305848 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5849 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5850
Ashish Jain83a6cc22016-06-28 14:34:17 +05305851 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305852 dst_format,
5853 buffer,
5854 src_format,
5855 frames);
5856
Ashish Jain83a6cc22016-06-28 14:34:17 +05305857 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305858 bytes_to_write);
5859
5860 /*Convert written bytes in audio flinger format*/
5861 if (ret > 0)
5862 ret = ((ret * format_to_bitwidth_table[out->format]) /
5863 format_to_bitwidth_table[dst_format]);
5864 }
5865 } else
5866 ret = compress_write(out->compr, buffer, bytes);
5867
Zhou Songc9672822017-08-16 16:01:39 +08005868 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5869 update_frames_written(out, bytes);
5870
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305871 if (ret < 0)
5872 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005873 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305874 /*msg to cb thread only if non blocking write is enabled*/
5875 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305876 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005877 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305878 } else if (-ENETRESET == ret) {
5879 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305880 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305881 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305882 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005883 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305884 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005885 }
Ashish Jain5106d362016-05-11 19:23:33 +05305886
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305887 /* Call compr start only when non-zero bytes of data is there to be rendered */
5888 if (!out->playback_started && ret > 0) {
5889 int status = compress_start(out->compr);
5890 if (status < 0) {
5891 ret = status;
5892 ALOGE("%s: compr start failed with err %d", __func__, errno);
5893 goto exit;
5894 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005895 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005896 out->playback_started = 1;
5897 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005898
5899 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5900 popcount(out->channel_mask),
5901 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005902 }
5903 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005904 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005905 return ret;
5906 } else {
5907 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005908 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005909 if (out->muted)
5910 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005911 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5912 __func__, frames, frame_size, bytes_to_write);
5913
Aalique Grahame22e49102018-12-18 14:23:57 -08005914 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005915 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5916 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5917 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005918 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5919 int16_t *src = (int16_t *)buffer;
5920 int16_t *dst = (int16_t *)buffer;
5921
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005922 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005923 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005924 "out_write called for %s use case with wrong properties",
5925 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005926
5927 /*
5928 * FIXME: this can be removed once audio flinger mixer supports
5929 * mono output
5930 */
5931
5932 /*
5933 * Code below goes over each frame in the buffer and adds both
5934 * L and R samples and then divides by 2 to convert to mono
5935 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005936 if (channel_count == 2) {
5937 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5938 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5939 }
5940 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005941 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005942 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07005943
5944 // Note: since out_get_presentation_position() is called alternating with out_write()
5945 // by AudioFlinger, we can check underruns using the prior timestamp read.
5946 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
5947 if (out->last_fifo_valid) {
5948 // compute drain to see if there is an underrun.
5949 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
5950 const int64_t frames_by_time =
5951 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
5952 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
5953
5954 if (underrun > 0) {
5955 simple_stats_log(&out->fifo_underruns, underrun);
5956
5957 ALOGW("%s: underrun(%lld) "
5958 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
5959 __func__,
5960 (long long)out->fifo_underruns.n,
5961 (long long)frames_by_time,
5962 (long long)out->last_fifo_frames_remaining);
5963 }
5964 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
5965 }
5966
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305967 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005968
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005969 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005970
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005971 if (out->config.rate)
5972 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5973 out->config.rate;
5974
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005975 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005976 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5977
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005978 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005979 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005980 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305981 out->convert_buffer != NULL) {
5982
5983 memcpy_by_audio_format(out->convert_buffer,
5984 out->hal_op_format,
5985 buffer,
5986 out->hal_ip_format,
5987 out->config.period_size * out->config.channels);
5988
5989 ret = pcm_write(out->pcm, out->convert_buffer,
5990 (out->config.period_size *
5991 out->config.channels *
5992 format_to_bitwidth_table[out->hal_op_format]));
5993 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305994 /*
5995 * To avoid underrun in DSP when the application is not pumping
5996 * data at required rate, check for the no. of bytes and ignore
5997 * pcm_write if it is less than actual buffer size.
5998 * It is a work around to a change in compress VOIP driver.
5999 */
6000 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6001 bytes < (out->config.period_size * out->config.channels *
6002 audio_bytes_per_sample(out->format))) {
6003 size_t voip_buf_size =
6004 out->config.period_size * out->config.channels *
6005 audio_bytes_per_sample(out->format);
6006 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6007 __func__, bytes, voip_buf_size);
6008 usleep(((uint64_t)voip_buf_size - bytes) *
6009 1000000 / audio_stream_out_frame_size(stream) /
6010 out_get_sample_rate(&out->stream.common));
6011 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006012 } else {
6013 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6014 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6015 else
6016 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6017 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306018 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006019
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006020 release_out_focus(out);
6021
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306022 if (ret < 0)
6023 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006024 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306025 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006026 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006027 }
6028
6029exit:
Zhou Songc9672822017-08-16 16:01:39 +08006030 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306031 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306032 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306033 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006034 pthread_mutex_unlock(&out->lock);
6035
6036 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006037 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006038 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306039 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306040 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306041 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306042 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306043 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306044 out->standby = true;
6045 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306046 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006047 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6048 /* prevent division-by-zero */
6049 uint32_t stream_size = audio_stream_out_frame_size(stream);
6050 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006051
Dieter Luecking5d57def2018-09-07 14:23:37 +02006052 if ((stream_size == 0) || (srate == 0)) {
6053 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6054 ATRACE_END();
6055 return -EINVAL;
6056 }
6057 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6058 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006059 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306060 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006061 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006062 return ret;
6063 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006064 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006065 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006066 return bytes;
6067}
6068
6069static int out_get_render_position(const struct audio_stream_out *stream,
6070 uint32_t *dsp_frames)
6071{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006072 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006073
6074 if (dsp_frames == NULL)
6075 return -EINVAL;
6076
6077 *dsp_frames = 0;
6078 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006079 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306080
6081 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6082 * this operation and adev_close_output_stream(where out gets reset).
6083 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306084 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006085 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306086 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006087 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306088 return 0;
6089 }
6090
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006091 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306092 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306093 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006094 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306095 if (ret < 0)
6096 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006097 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306098 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006099 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306100 if (-ENETRESET == ret) {
6101 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306102 out->card_status = CARD_STATUS_OFFLINE;
6103 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306104 } else if(ret < 0) {
6105 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306106 ret = -EINVAL;
6107 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306108 /*
6109 * Handle corner case where compress session is closed during SSR
6110 * and timestamp is queried
6111 */
6112 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306113 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306114 } else if (out->prev_card_status_offline) {
6115 ALOGE("ERROR: previously sound card was offline,return error");
6116 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306117 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306118 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006119 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306120 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306121 pthread_mutex_unlock(&out->lock);
6122 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006123 } else if (audio_is_linear_pcm(out->format)) {
6124 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006125 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006126 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006127 } else
6128 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006129}
6130
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006131static int out_add_audio_effect(const struct audio_stream *stream __unused,
6132 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006133{
6134 return 0;
6135}
6136
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006137static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6138 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006139{
6140 return 0;
6141}
6142
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006143static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6144 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006145{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306146 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006147}
6148
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006149static int out_get_presentation_position(const struct audio_stream_out *stream,
6150 uint64_t *frames, struct timespec *timestamp)
6151{
6152 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306153 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006154 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006155
Ashish Jain5106d362016-05-11 19:23:33 +05306156 /* below piece of code is not guarded against any lock because audioFliner serializes
6157 * this operation and adev_close_output_stream( where out gets reset).
6158 */
6159 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306160 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006161 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306162 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6163 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6164 return 0;
6165 }
6166
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006167 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006168
Ashish Jain5106d362016-05-11 19:23:33 +05306169 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6170 ret = compress_get_tstamp(out->compr, &dsp_frames,
6171 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006172 // Adjustment accounts for A2dp encoder latency with offload usecases
6173 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006174 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006175 unsigned long offset =
6176 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6177 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6178 }
Ashish Jain5106d362016-05-11 19:23:33 +05306179 ALOGVV("%s rendered frames %ld sample_rate %d",
6180 __func__, dsp_frames, out->sample_rate);
6181 *frames = dsp_frames;
6182 if (ret < 0)
6183 ret = -errno;
6184 if (-ENETRESET == ret) {
6185 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306186 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306187 ret = -EINVAL;
6188 } else
6189 ret = 0;
6190 /* this is the best we can do */
6191 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006192 } else {
6193 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006194 unsigned int avail;
6195 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006196 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006197 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006198
Andy Hunga1f48fa2019-07-01 18:14:53 -07006199 if (out->kernel_buffer_size > avail) {
6200 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6201 } else {
6202 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6203 __func__, avail, out->kernel_buffer_size);
6204 avail = out->kernel_buffer_size;
6205 frames_temp = out->last_fifo_frames_remaining = 0;
6206 }
6207 out->last_fifo_valid = true;
6208 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6209
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006210 if (out->written >= frames_temp)
6211 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006212
Andy Hunga1f48fa2019-07-01 18:14:53 -07006213 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6214 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6215
Weiyin Jiangd4633762018-03-16 12:05:03 +08006216 // This adjustment accounts for buffering after app processor.
6217 // It is based on estimated DSP latency per use case, rather than exact.
Robert Lee58215542019-07-15 20:55:12 +08006218 pthread_mutex_lock(&adev->lock);
6219 frames_temp = platform_render_latency(out->dev, out->usecase) *
6220 out->sample_rate / 1000000LL;
6221 pthread_mutex_unlock(&adev->lock);
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006222 if (signed_frames >= frames_temp)
6223 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006224
Weiyin Jiangd4633762018-03-16 12:05:03 +08006225 // Adjustment accounts for A2dp encoder latency with non offload usecases
6226 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006227 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006228 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6229 if (signed_frames >= frames_temp)
6230 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006231 }
6232
6233 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006234 *frames = signed_frames;
6235 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006236 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006237 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6238 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006239 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306240 *frames = out->written;
6241 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306242 if (is_offload_usecase(out->usecase))
6243 ret = -EINVAL;
6244 else
6245 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006246 }
6247 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006248 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006249 return ret;
6250}
6251
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006252static int out_set_callback(struct audio_stream_out *stream,
6253 stream_callback_t callback, void *cookie)
6254{
6255 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006256 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006257
6258 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006259 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006260 out->client_callback = callback;
6261 out->client_cookie = cookie;
6262 if (out->adsp_hdlr_stream_handle) {
6263 ret = audio_extn_adsp_hdlr_stream_set_callback(
6264 out->adsp_hdlr_stream_handle,
6265 callback,
6266 cookie);
6267 if (ret)
6268 ALOGW("%s:adsp hdlr callback registration failed %d",
6269 __func__, ret);
6270 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006271 pthread_mutex_unlock(&out->lock);
6272 return 0;
6273}
6274
6275static int out_pause(struct audio_stream_out* stream)
6276{
6277 struct stream_out *out = (struct stream_out *)stream;
6278 int status = -ENOSYS;
6279 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006280 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006281 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306282 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006283 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006284 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306285 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306286 status = compress_pause(out->compr);
6287
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006288 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006289
Mingming Yin21854652016-04-13 11:54:02 -07006290 if (audio_extn_passthru_is_active()) {
6291 ALOGV("offload use case, pause passthru");
6292 audio_extn_passthru_on_pause(out);
6293 }
6294
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306295 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006296 audio_extn_dts_notify_playback_state(out->usecase, 0,
6297 out->sample_rate, popcount(out->channel_mask),
6298 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006299 }
6300 pthread_mutex_unlock(&out->lock);
6301 }
6302 return status;
6303}
6304
6305static int out_resume(struct audio_stream_out* stream)
6306{
6307 struct stream_out *out = (struct stream_out *)stream;
6308 int status = -ENOSYS;
6309 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006310 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006311 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306312 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006313 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006314 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306315 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306316 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006317 }
6318 if (!status) {
6319 out->offload_state = OFFLOAD_STATE_PLAYING;
6320 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306321 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006322 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6323 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006324 }
6325 pthread_mutex_unlock(&out->lock);
6326 }
6327 return status;
6328}
6329
6330static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6331{
6332 struct stream_out *out = (struct stream_out *)stream;
6333 int status = -ENOSYS;
6334 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006335 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006336 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006337 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6338 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6339 else
6340 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6341 pthread_mutex_unlock(&out->lock);
6342 }
6343 return status;
6344}
6345
6346static int out_flush(struct audio_stream_out* stream)
6347{
6348 struct stream_out *out = (struct stream_out *)stream;
6349 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006350 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006351 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006352 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006353 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6354 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006355 } else {
6356 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6357 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006358 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006359 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006360 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006361 return 0;
6362 }
6363 return -ENOSYS;
6364}
6365
Haynes Mathew George16081042017-05-31 17:16:49 -07006366static int out_stop(const struct audio_stream_out* stream)
6367{
6368 struct stream_out *out = (struct stream_out *)stream;
6369 struct audio_device *adev = out->dev;
6370 int ret = -ENOSYS;
6371
6372 ALOGV("%s", __func__);
6373 pthread_mutex_lock(&adev->lock);
6374 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6375 out->playback_started && out->pcm != NULL) {
6376 pcm_stop(out->pcm);
6377 ret = stop_output_stream(out);
6378 out->playback_started = false;
6379 }
6380 pthread_mutex_unlock(&adev->lock);
6381 return ret;
6382}
6383
6384static int out_start(const struct audio_stream_out* stream)
6385{
6386 struct stream_out *out = (struct stream_out *)stream;
6387 struct audio_device *adev = out->dev;
6388 int ret = -ENOSYS;
6389
6390 ALOGV("%s", __func__);
6391 pthread_mutex_lock(&adev->lock);
6392 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6393 !out->playback_started && out->pcm != NULL) {
6394 ret = start_output_stream(out);
6395 if (ret == 0) {
6396 out->playback_started = true;
6397 }
6398 }
6399 pthread_mutex_unlock(&adev->lock);
6400 return ret;
6401}
6402
6403/*
6404 * Modify config->period_count based on min_size_frames
6405 */
6406static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6407{
6408 int periodCountRequested = (min_size_frames + config->period_size - 1)
6409 / config->period_size;
6410 int periodCount = MMAP_PERIOD_COUNT_MIN;
6411
6412 ALOGV("%s original config.period_size = %d config.period_count = %d",
6413 __func__, config->period_size, config->period_count);
6414
6415 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6416 periodCount *= 2;
6417 }
6418 config->period_count = periodCount;
6419
6420 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6421}
6422
Phil Burkfe17efd2019-03-25 10:23:35 -07006423// Read offset for the positional timestamp from a persistent vendor property.
6424// This is to workaround apparent inaccuracies in the timing information that
6425// is used by the AAudio timing model. The inaccuracies can cause glitches.
6426static int64_t get_mmap_out_time_offset() {
6427 const int32_t kDefaultOffsetMicros = 0;
6428 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006429 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006430 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6431 return mmap_time_offset_micros * (int64_t)1000;
6432}
6433
Haynes Mathew George16081042017-05-31 17:16:49 -07006434static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6435 int32_t min_size_frames,
6436 struct audio_mmap_buffer_info *info)
6437{
6438 struct stream_out *out = (struct stream_out *)stream;
6439 struct audio_device *adev = out->dev;
6440 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006441 unsigned int offset1 = 0;
6442 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006443 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006444 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006445 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006446
Arun Mirpuri5d170872019-03-26 13:21:31 -07006447 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306448 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006449 pthread_mutex_lock(&adev->lock);
6450
Sharad Sanglec6f32552018-05-04 16:15:38 +05306451 if (CARD_STATUS_OFFLINE == out->card_status ||
6452 CARD_STATUS_OFFLINE == adev->card_status) {
6453 ALOGW("out->card_status or adev->card_status offline, try again");
6454 ret = -EIO;
6455 goto exit;
6456 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306457 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006458 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6459 ret = -EINVAL;
6460 goto exit;
6461 }
6462 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6463 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6464 ret = -ENOSYS;
6465 goto exit;
6466 }
6467 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6468 if (out->pcm_device_id < 0) {
6469 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6470 __func__, out->pcm_device_id, out->usecase);
6471 ret = -EINVAL;
6472 goto exit;
6473 }
6474
6475 adjust_mmap_period_count(&out->config, min_size_frames);
6476
Arun Mirpuri5d170872019-03-26 13:21:31 -07006477 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006478 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6479 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6480 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306481 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306482 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6483 out->card_status = CARD_STATUS_OFFLINE;
6484 adev->card_status = CARD_STATUS_OFFLINE;
6485 ret = -EIO;
6486 goto exit;
6487 }
6488
Haynes Mathew George16081042017-05-31 17:16:49 -07006489 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6490 step = "open";
6491 ret = -ENODEV;
6492 goto exit;
6493 }
6494 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6495 if (ret < 0) {
6496 step = "begin";
6497 goto exit;
6498 }
juyuchen626833d2019-06-04 16:48:02 +08006499
6500 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006501 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006502 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006503 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006504 ret = platform_get_mmap_data_fd(adev->platform,
6505 out->pcm_device_id, 0 /*playback*/,
6506 &info->shared_memory_fd,
6507 &mmap_size);
6508 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006509 // Fall back to non exclusive mode
6510 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6511 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006512 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6513 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6514
Arun Mirpuri5d170872019-03-26 13:21:31 -07006515 if (mmap_size < buffer_size) {
6516 step = "mmap";
6517 goto exit;
6518 }
juyuchen626833d2019-06-04 16:48:02 +08006519 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006520 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006521 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006522 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006523
6524 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6525 if (ret < 0) {
6526 step = "commit";
6527 goto exit;
6528 }
6529
Phil Burkfe17efd2019-03-25 10:23:35 -07006530 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6531
Haynes Mathew George16081042017-05-31 17:16:49 -07006532 out->standby = false;
6533 ret = 0;
6534
Arun Mirpuri5d170872019-03-26 13:21:31 -07006535 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006536 __func__, info->shared_memory_address, info->buffer_size_frames);
6537
6538exit:
6539 if (ret != 0) {
6540 if (out->pcm == NULL) {
6541 ALOGE("%s: %s - %d", __func__, step, ret);
6542 } else {
6543 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6544 pcm_close(out->pcm);
6545 out->pcm = NULL;
6546 }
6547 }
6548 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306549 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006550 return ret;
6551}
6552
6553static int out_get_mmap_position(const struct audio_stream_out *stream,
6554 struct audio_mmap_position *position)
6555{
6556 struct stream_out *out = (struct stream_out *)stream;
6557 ALOGVV("%s", __func__);
6558 if (position == NULL) {
6559 return -EINVAL;
6560 }
6561 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006562 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006563 return -ENOSYS;
6564 }
6565 if (out->pcm == NULL) {
6566 return -ENOSYS;
6567 }
6568
6569 struct timespec ts = { 0, 0 };
6570 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6571 if (ret < 0) {
6572 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6573 return ret;
6574 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006575 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6576 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006577 return 0;
6578}
6579
6580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006581/** audio_stream_in implementation **/
6582static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6583{
6584 struct stream_in *in = (struct stream_in *)stream;
6585
6586 return in->config.rate;
6587}
6588
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006589static int in_set_sample_rate(struct audio_stream *stream __unused,
6590 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006591{
6592 return -ENOSYS;
6593}
6594
6595static size_t in_get_buffer_size(const struct audio_stream *stream)
6596{
6597 struct stream_in *in = (struct stream_in *)stream;
6598
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006599 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6600 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006601 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6602 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306603 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306604 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006605
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006606 return in->config.period_size * in->af_period_multiplier *
6607 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006608}
6609
6610static uint32_t in_get_channels(const struct audio_stream *stream)
6611{
6612 struct stream_in *in = (struct stream_in *)stream;
6613
6614 return in->channel_mask;
6615}
6616
6617static audio_format_t in_get_format(const struct audio_stream *stream)
6618{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006619 struct stream_in *in = (struct stream_in *)stream;
6620
6621 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006622}
6623
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006624static int in_set_format(struct audio_stream *stream __unused,
6625 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006626{
6627 return -ENOSYS;
6628}
6629
6630static int in_standby(struct audio_stream *stream)
6631{
6632 struct stream_in *in = (struct stream_in *)stream;
6633 struct audio_device *adev = in->dev;
6634 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306635 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6636 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006637 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306638
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006639 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006640 if (!in->standby && in->is_st_session) {
6641 ALOGD("%s: sound trigger pcm stop lab", __func__);
6642 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006643 if (adev->num_va_sessions > 0)
6644 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006645 in->standby = 1;
6646 }
6647
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006648 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006649 if (adev->adm_deregister_stream)
6650 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6651
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006652 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006653 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006654 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006655 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006656 voice_extn_compress_voip_close_input_stream(stream);
6657 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006658 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6659 do_stop = in->capture_started;
6660 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006661 if (in->mmap_shared_memory_fd >= 0) {
6662 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6663 __func__, in->mmap_shared_memory_fd);
6664 close(in->mmap_shared_memory_fd);
6665 in->mmap_shared_memory_fd = -1;
6666 }
Zhou Songa8895042016-07-05 17:54:22 +08006667 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306668 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306669 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006670 }
6671
Arun Mirpuri5d170872019-03-26 13:21:31 -07006672 if (in->pcm) {
6673 ATRACE_BEGIN("pcm_in_close");
6674 pcm_close(in->pcm);
6675 ATRACE_END();
6676 in->pcm = NULL;
6677 }
6678
Carter Hsu2e429db2019-05-14 18:50:52 +08006679 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006680 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006681
George Gao3018ede2019-10-23 13:23:00 -07006682 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6683 if (adev->num_va_sessions > 0)
6684 adev->num_va_sessions--;
6685 }
Quinn Malef6050362019-01-30 15:55:40 -08006686
Eric Laurent150dbfe2013-02-27 14:31:02 -08006687 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006688 }
6689 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006690 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006691 return status;
6692}
6693
Aalique Grahame22e49102018-12-18 14:23:57 -08006694static int in_dump(const struct audio_stream *stream,
6695 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006696{
Aalique Grahame22e49102018-12-18 14:23:57 -08006697 struct stream_in *in = (struct stream_in *)stream;
6698
6699 // We try to get the lock for consistency,
6700 // but it isn't necessary for these variables.
6701 // If we're not in standby, we may be blocked on a read.
6702 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6703 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6704 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6705 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6706
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006707 char buffer[256]; // for statistics formatting
6708 if (in->start_latency_ms.n > 0) {
6709 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6710 dprintf(fd, " Start latency ms: %s\n", buffer);
6711 }
6712
Aalique Grahame22e49102018-12-18 14:23:57 -08006713 if (locked) {
6714 pthread_mutex_unlock(&in->lock);
6715 }
6716
6717 // dump error info
6718 (void)error_log_dump(
6719 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006721 return 0;
6722}
6723
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306724static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6725{
6726 if (!stream || !parms)
6727 return;
6728
6729 struct stream_in *in = (struct stream_in *)stream;
6730 struct audio_device *adev = in->dev;
6731
6732 card_status_t status;
6733 int card;
6734 if (parse_snd_card_status(parms, &card, &status) < 0)
6735 return;
6736
6737 pthread_mutex_lock(&adev->lock);
6738 bool valid_cb = (card == adev->snd_card);
6739 pthread_mutex_unlock(&adev->lock);
6740
6741 if (!valid_cb)
6742 return;
6743
6744 lock_input_stream(in);
6745 if (in->card_status != status)
6746 in->card_status = status;
6747 pthread_mutex_unlock(&in->lock);
6748
6749 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6750 use_case_table[in->usecase],
6751 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6752
6753 // a better solution would be to report error back to AF and let
6754 // it put the stream to standby
6755 if (status == CARD_STATUS_OFFLINE)
6756 in_standby(&in->stream.common);
6757
6758 return;
6759}
6760
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006761int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006762 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006763 audio_source_t source)
6764{
6765 struct audio_device *adev = in->dev;
6766 int ret = 0;
6767
6768 lock_input_stream(in);
6769 pthread_mutex_lock(&adev->lock);
6770
6771 /* no audio source uses val == 0 */
6772 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6773 in->source = source;
6774 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6775 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6776 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6777 (in->config.rate == 8000 || in->config.rate == 16000 ||
6778 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6779 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6780 ret = voice_extn_compress_voip_open_input_stream(in);
6781 if (ret != 0) {
6782 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6783 __func__, ret);
6784 }
6785 }
6786 }
6787
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006788 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6789 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006790 // Workaround: If routing to an non existing usb device, fail gracefully
6791 // The routing request will otherwise block during 10 second
6792 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006793 struct str_parms *usb_addr =
6794 str_parms_create_str(get_usb_device_address(devices));
6795 if (is_usb_in_device_type(devices) && usb_addr &&
6796 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006797 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6798 ret = -ENOSYS;
6799 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006800 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006801 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006802 if (!in->standby && !in->is_st_session) {
6803 ALOGV("update input routing change");
6804 // inform adm before actual routing to prevent glitches.
6805 if (adev->adm_on_routing_change) {
6806 adev->adm_on_routing_change(adev->adm_data,
6807 in->capture_handle);
6808 ret = select_devices(adev, in->usecase);
6809 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6810 adev->adm_routing_changed = true;
6811 }
6812 }
6813 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006814 if (usb_addr)
6815 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006816 }
6817 pthread_mutex_unlock(&adev->lock);
6818 pthread_mutex_unlock(&in->lock);
6819
6820 ALOGD("%s: exit: status(%d)", __func__, ret);
6821 return ret;
6822}
6823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006824static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6825{
6826 struct stream_in *in = (struct stream_in *)stream;
6827 struct audio_device *adev = in->dev;
6828 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006829 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306830 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006831
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306832 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006833 parms = str_parms_create_str(kvpairs);
6834
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306835 if (!parms)
6836 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006837 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006838 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006839
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306840 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6841 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306842 strlcpy(in->profile, value, sizeof(in->profile));
6843 ALOGV("updating stream profile with value '%s'", in->profile);
6844 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6845 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006846 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306847 in->sample_rate, in->bit_width,
6848 in->profile, &in->app_type_cfg);
6849 }
6850
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006851 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006852 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006853
6854 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306855error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306856 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006857}
6858
6859static char* in_get_parameters(const struct audio_stream *stream,
6860 const char *keys)
6861{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006862 struct stream_in *in = (struct stream_in *)stream;
6863 struct str_parms *query = str_parms_create_str(keys);
6864 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006865 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006866
6867 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006868 if (reply) {
6869 str_parms_destroy(reply);
6870 }
6871 if (query) {
6872 str_parms_destroy(query);
6873 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006874 ALOGE("in_get_parameters: failed to create query or reply");
6875 return NULL;
6876 }
6877
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006878 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006879
6880 voice_extn_in_get_parameters(in, query, reply);
6881
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006882 stream_get_parameter_channels(query, reply,
6883 &in->supported_channel_masks[0]);
6884 stream_get_parameter_formats(query, reply,
6885 &in->supported_formats[0]);
6886 stream_get_parameter_rates(query, reply,
6887 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006888 str = str_parms_to_str(reply);
6889 str_parms_destroy(query);
6890 str_parms_destroy(reply);
6891
6892 ALOGV("%s: exit: returns - %s", __func__, str);
6893 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006894}
6895
Aalique Grahame22e49102018-12-18 14:23:57 -08006896static int in_set_gain(struct audio_stream_in *stream,
6897 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006898{
Aalique Grahame22e49102018-12-18 14:23:57 -08006899 struct stream_in *in = (struct stream_in *)stream;
6900 char mixer_ctl_name[128];
6901 struct mixer_ctl *ctl;
6902 int ctl_value;
6903
6904 ALOGV("%s: gain %f", __func__, gain);
6905
6906 if (stream == NULL)
6907 return -EINVAL;
6908
6909 /* in_set_gain() only used to silence MMAP capture for now */
6910 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6911 return -ENOSYS;
6912
6913 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6914
6915 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6916 if (!ctl) {
6917 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6918 __func__, mixer_ctl_name);
6919 return -ENOSYS;
6920 }
6921
6922 if (gain < RECORD_GAIN_MIN)
6923 gain = RECORD_GAIN_MIN;
6924 else if (gain > RECORD_GAIN_MAX)
6925 gain = RECORD_GAIN_MAX;
6926 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6927
6928 mixer_ctl_set_value(ctl, 0, ctl_value);
6929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006930 return 0;
6931}
6932
6933static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6934 size_t bytes)
6935{
6936 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306937
6938 if (in == NULL) {
6939 ALOGE("%s: stream_in ptr is NULL", __func__);
6940 return -EINVAL;
6941 }
6942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006943 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306944 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306945 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006946
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006947 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306948
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006949 if (in->is_st_session) {
6950 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6951 /* Read from sound trigger HAL */
6952 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006953 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006954 if (adev->num_va_sessions < UINT_MAX)
6955 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006956 in->standby = 0;
6957 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006958 pthread_mutex_unlock(&in->lock);
6959 return bytes;
6960 }
6961
Haynes Mathew George16081042017-05-31 17:16:49 -07006962 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6963 ret = -ENOSYS;
6964 goto exit;
6965 }
6966
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006967 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6968 !in->standby && adev->adm_routing_changed) {
6969 ret = -ENOSYS;
6970 goto exit;
6971 }
6972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006973 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006974 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6975
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006976 pthread_mutex_lock(&adev->lock);
6977 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6978 ret = voice_extn_compress_voip_start_input_stream(in);
6979 else
6980 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006981 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6982 if (adev->num_va_sessions < UINT_MAX)
6983 adev->num_va_sessions++;
6984 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006985 pthread_mutex_unlock(&adev->lock);
6986 if (ret != 0) {
6987 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006988 }
6989 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006990
6991 // log startup time in ms.
6992 simple_stats_log(
6993 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006994 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006995
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306996 /* Avoid read if capture_stopped is set */
6997 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6998 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6999 ret = -EINVAL;
7000 goto exit;
7001 }
7002
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007003 // what's the duration requested by the client?
7004 long ns = 0;
7005
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307006 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007007 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7008 in->config.rate;
7009
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007010 ret = request_in_focus(in, ns);
7011 if (ret != 0)
7012 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007013 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007014
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307015 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307016 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7017 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307018 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007019 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307020 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007021 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007022 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007023 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007024 } else if (audio_extn_ffv_get_stream() == in) {
7025 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307026 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007027 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307028 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7029 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7030 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7031 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307032 ret = -EINVAL;
7033 goto exit;
7034 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307035 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307036 ret = -errno;
7037 }
7038 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307039 /* bytes read is always set to bytes for non compress usecases */
7040 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007041 }
7042
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007043 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007045 /*
Quinn Malef6050362019-01-30 15:55:40 -08007046 * Instead of writing zeroes here, we could trust the hardware to always
7047 * provide zeroes when muted. This is also muted with voice recognition
7048 * usecases so that other clients do not have access to voice recognition
7049 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007050 */
Quinn Malef6050362019-01-30 15:55:40 -08007051 if ((ret == 0 && voice_get_mic_mute(adev) &&
7052 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007053 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7054 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007055 (adev->num_va_sessions &&
7056 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7057 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7058 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007059 memset(buffer, 0, bytes);
7060
7061exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307062 frame_size = audio_stream_in_frame_size(stream);
7063 if (frame_size > 0)
7064 in->frames_read += bytes_read/frame_size;
7065
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007066 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307067 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007068 pthread_mutex_unlock(&in->lock);
7069
7070 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307071 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307072 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307073 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307074 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307075 in->standby = true;
7076 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307077 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307078 bytes_read = bytes;
7079 memset(buffer, 0, bytes);
7080 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007081 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007082 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7083 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007084 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307085 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307086 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007087 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307088 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007089}
7090
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007091static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007092{
7093 return 0;
7094}
7095
Aalique Grahame22e49102018-12-18 14:23:57 -08007096static int in_get_capture_position(const struct audio_stream_in *stream,
7097 int64_t *frames, int64_t *time)
7098{
7099 if (stream == NULL || frames == NULL || time == NULL) {
7100 return -EINVAL;
7101 }
7102 struct stream_in *in = (struct stream_in *)stream;
7103 int ret = -ENOSYS;
7104
7105 lock_input_stream(in);
7106 // note: ST sessions do not close the alsa pcm driver synchronously
7107 // on standby. Therefore, we may return an error even though the
7108 // pcm stream is still opened.
7109 if (in->standby) {
7110 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7111 "%s stream in standby but pcm not NULL for non ST session", __func__);
7112 goto exit;
7113 }
7114 if (in->pcm) {
7115 struct timespec timestamp;
7116 unsigned int avail;
7117 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7118 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007119 pthread_mutex_lock(&adev->lock);
7120 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
7121 - platform_capture_latency(in->dev, in->usecase) * 1000LL;
7122 pthread_mutex_unlock(&adev->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08007123 ret = 0;
7124 }
7125 }
7126exit:
7127 pthread_mutex_unlock(&in->lock);
7128 return ret;
7129}
7130
Carter Hsu2e429db2019-05-14 18:50:52 +08007131static int in_update_effect_list(bool add, effect_handle_t effect,
7132 struct listnode *head)
7133{
7134 struct listnode *node;
7135 struct in_effect_list *elist = NULL;
7136 struct in_effect_list *target = NULL;
7137 int ret = 0;
7138
7139 if (!head)
7140 return ret;
7141
7142 list_for_each(node, head) {
7143 elist = node_to_item(node, struct in_effect_list, list);
7144 if (elist->handle == effect) {
7145 target = elist;
7146 break;
7147 }
7148 }
7149
7150 if (add) {
7151 if (target) {
7152 ALOGD("effect %p already exist", effect);
7153 return ret;
7154 }
7155
7156 target = (struct in_effect_list *)
7157 calloc(1, sizeof(struct in_effect_list));
7158
7159 if (!target) {
7160 ALOGE("%s:fail to allocate memory", __func__);
7161 return -ENOMEM;
7162 }
7163
7164 target->handle = effect;
7165 list_add_tail(head, &target->list);
7166 } else {
7167 if (target) {
7168 list_remove(&target->list);
7169 free(target);
7170 }
7171 }
7172
7173 return ret;
7174}
7175
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007176static int add_remove_audio_effect(const struct audio_stream *stream,
7177 effect_handle_t effect,
7178 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007179{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007180 struct stream_in *in = (struct stream_in *)stream;
7181 int status = 0;
7182 effect_descriptor_t desc;
7183
7184 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007185 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7186
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007187 if (status != 0)
7188 return status;
7189
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007190 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007191 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007192 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007193 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7194 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007195 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007196
7197 in_update_effect_list(enable, effect, &in->aec_list);
7198 enable = !list_empty(&in->aec_list);
7199 if (enable == in->enable_aec)
7200 goto exit;
7201
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007202 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007203 ALOGD("AEC enable %d", enable);
7204
Aalique Grahame22e49102018-12-18 14:23:57 -08007205 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7206 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7207 in->dev->enable_voicerx = enable;
7208 struct audio_usecase *usecase;
7209 struct listnode *node;
7210 list_for_each(node, &in->dev->usecase_list) {
7211 usecase = node_to_item(node, struct audio_usecase, list);
7212 if (usecase->type == PCM_PLAYBACK)
7213 select_devices(in->dev, usecase->id);
7214 }
7215 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007216 if (!in->standby) {
7217 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7218 select_devices(in->dev, in->usecase);
7219 }
7220
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007221 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007222 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7223
7224 in_update_effect_list(enable, effect, &in->ns_list);
7225 enable = !list_empty(&in->ns_list);
7226 if (enable == in->enable_ns)
7227 goto exit;
7228
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007229 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007230 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007231 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007232 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7233 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007234 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7235 select_devices(in->dev, in->usecase);
7236 } else
7237 select_devices(in->dev, in->usecase);
7238 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007239 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007240exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007241 pthread_mutex_unlock(&in->dev->lock);
7242 pthread_mutex_unlock(&in->lock);
7243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007244 return 0;
7245}
7246
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007247static int in_add_audio_effect(const struct audio_stream *stream,
7248 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007249{
Eric Laurent994a6932013-07-17 11:51:42 -07007250 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007251 return add_remove_audio_effect(stream, effect, true);
7252}
7253
7254static int in_remove_audio_effect(const struct audio_stream *stream,
7255 effect_handle_t effect)
7256{
Eric Laurent994a6932013-07-17 11:51:42 -07007257 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007258 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007259}
7260
Derek Chenf939fb72018-11-13 13:34:41 -08007261streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7262 audio_io_handle_t input)
7263{
7264 struct listnode *node;
7265
7266 list_for_each(node, &dev->active_inputs_list) {
7267 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7268 streams_input_ctxt_t,
7269 list);
7270 if (in_ctxt->input->capture_handle == input) {
7271 return in_ctxt;
7272 }
7273 }
7274 return NULL;
7275}
7276
7277streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7278 audio_io_handle_t output)
7279{
7280 struct listnode *node;
7281
7282 list_for_each(node, &dev->active_outputs_list) {
7283 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7284 streams_output_ctxt_t,
7285 list);
7286 if (out_ctxt->output->handle == output) {
7287 return out_ctxt;
7288 }
7289 }
7290 return NULL;
7291}
7292
Haynes Mathew George16081042017-05-31 17:16:49 -07007293static int in_stop(const struct audio_stream_in* stream)
7294{
7295 struct stream_in *in = (struct stream_in *)stream;
7296 struct audio_device *adev = in->dev;
7297
7298 int ret = -ENOSYS;
7299 ALOGV("%s", __func__);
7300 pthread_mutex_lock(&adev->lock);
7301 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7302 in->capture_started && in->pcm != NULL) {
7303 pcm_stop(in->pcm);
7304 ret = stop_input_stream(in);
7305 in->capture_started = false;
7306 }
7307 pthread_mutex_unlock(&adev->lock);
7308 return ret;
7309}
7310
7311static int in_start(const struct audio_stream_in* stream)
7312{
7313 struct stream_in *in = (struct stream_in *)stream;
7314 struct audio_device *adev = in->dev;
7315 int ret = -ENOSYS;
7316
7317 ALOGV("%s in %p", __func__, in);
7318 pthread_mutex_lock(&adev->lock);
7319 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7320 !in->capture_started && in->pcm != NULL) {
7321 if (!in->capture_started) {
7322 ret = start_input_stream(in);
7323 if (ret == 0) {
7324 in->capture_started = true;
7325 }
7326 }
7327 }
7328 pthread_mutex_unlock(&adev->lock);
7329 return ret;
7330}
7331
Phil Burke0a86d12019-02-16 22:28:11 -08007332// Read offset for the positional timestamp from a persistent vendor property.
7333// This is to workaround apparent inaccuracies in the timing information that
7334// is used by the AAudio timing model. The inaccuracies can cause glitches.
7335static int64_t in_get_mmap_time_offset() {
7336 const int32_t kDefaultOffsetMicros = 0;
7337 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007338 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007339 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7340 return mmap_time_offset_micros * (int64_t)1000;
7341}
7342
Haynes Mathew George16081042017-05-31 17:16:49 -07007343static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7344 int32_t min_size_frames,
7345 struct audio_mmap_buffer_info *info)
7346{
7347 struct stream_in *in = (struct stream_in *)stream;
7348 struct audio_device *adev = in->dev;
7349 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007350 unsigned int offset1 = 0;
7351 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007352 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007353 uint32_t mmap_size = 0;
7354 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007355
7356 pthread_mutex_lock(&adev->lock);
7357 ALOGV("%s in %p", __func__, in);
7358
Sharad Sanglec6f32552018-05-04 16:15:38 +05307359 if (CARD_STATUS_OFFLINE == in->card_status||
7360 CARD_STATUS_OFFLINE == adev->card_status) {
7361 ALOGW("in->card_status or adev->card_status offline, try again");
7362 ret = -EIO;
7363 goto exit;
7364 }
7365
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307366 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007367 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7368 ret = -EINVAL;
7369 goto exit;
7370 }
7371 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7372 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7373 ALOGV("%s in %p", __func__, in);
7374 ret = -ENOSYS;
7375 goto exit;
7376 }
7377 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7378 if (in->pcm_device_id < 0) {
7379 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7380 __func__, in->pcm_device_id, in->usecase);
7381 ret = -EINVAL;
7382 goto exit;
7383 }
7384
7385 adjust_mmap_period_count(&in->config, min_size_frames);
7386
7387 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7388 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7389 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7390 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307391 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307392 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7393 in->card_status = CARD_STATUS_OFFLINE;
7394 adev->card_status = CARD_STATUS_OFFLINE;
7395 ret = -EIO;
7396 goto exit;
7397 }
7398
Haynes Mathew George16081042017-05-31 17:16:49 -07007399 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7400 step = "open";
7401 ret = -ENODEV;
7402 goto exit;
7403 }
7404
7405 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7406 if (ret < 0) {
7407 step = "begin";
7408 goto exit;
7409 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007410
juyuchen626833d2019-06-04 16:48:02 +08007411 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007412 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7413 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7414 info->burst_size_frames = in->config.period_size;
7415 ret = platform_get_mmap_data_fd(adev->platform,
7416 in->pcm_device_id, 1 /*capture*/,
7417 &info->shared_memory_fd,
7418 &mmap_size);
7419 if (ret < 0) {
7420 // Fall back to non exclusive mode
7421 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7422 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007423 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7424 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7425
Arun Mirpuri5d170872019-03-26 13:21:31 -07007426 if (mmap_size < buffer_size) {
7427 step = "mmap";
7428 goto exit;
7429 }
juyuchen626833d2019-06-04 16:48:02 +08007430 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007431 }
7432
7433 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007434
7435 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7436 if (ret < 0) {
7437 step = "commit";
7438 goto exit;
7439 }
7440
Phil Burke0a86d12019-02-16 22:28:11 -08007441 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7442
Haynes Mathew George16081042017-05-31 17:16:49 -07007443 in->standby = false;
7444 ret = 0;
7445
7446 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7447 __func__, info->shared_memory_address, info->buffer_size_frames);
7448
7449exit:
7450 if (ret != 0) {
7451 if (in->pcm == NULL) {
7452 ALOGE("%s: %s - %d", __func__, step, ret);
7453 } else {
7454 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7455 pcm_close(in->pcm);
7456 in->pcm = NULL;
7457 }
7458 }
7459 pthread_mutex_unlock(&adev->lock);
7460 return ret;
7461}
7462
7463static int in_get_mmap_position(const struct audio_stream_in *stream,
7464 struct audio_mmap_position *position)
7465{
7466 struct stream_in *in = (struct stream_in *)stream;
7467 ALOGVV("%s", __func__);
7468 if (position == NULL) {
7469 return -EINVAL;
7470 }
7471 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7472 return -ENOSYS;
7473 }
7474 if (in->pcm == NULL) {
7475 return -ENOSYS;
7476 }
7477 struct timespec ts = { 0, 0 };
7478 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7479 if (ret < 0) {
7480 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7481 return ret;
7482 }
Phil Burke0a86d12019-02-16 22:28:11 -08007483 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7484 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007485 return 0;
7486}
7487
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307488static int in_get_active_microphones(const struct audio_stream_in *stream,
7489 struct audio_microphone_characteristic_t *mic_array,
7490 size_t *mic_count) {
7491 struct stream_in *in = (struct stream_in *)stream;
7492 struct audio_device *adev = in->dev;
7493 ALOGVV("%s", __func__);
7494
7495 lock_input_stream(in);
7496 pthread_mutex_lock(&adev->lock);
7497 int ret = platform_get_active_microphones(adev->platform,
7498 audio_channel_count_from_in_mask(in->channel_mask),
7499 in->usecase, mic_array, mic_count);
7500 pthread_mutex_unlock(&adev->lock);
7501 pthread_mutex_unlock(&in->lock);
7502
7503 return ret;
7504}
7505
7506static int adev_get_microphones(const struct audio_hw_device *dev,
7507 struct audio_microphone_characteristic_t *mic_array,
7508 size_t *mic_count) {
7509 struct audio_device *adev = (struct audio_device *)dev;
7510 ALOGVV("%s", __func__);
7511
7512 pthread_mutex_lock(&adev->lock);
7513 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7514 pthread_mutex_unlock(&adev->lock);
7515
7516 return ret;
7517}
juyuchendb308c22019-01-21 11:57:17 -07007518
7519static void in_update_sink_metadata(struct audio_stream_in *stream,
7520 const struct sink_metadata *sink_metadata) {
7521
7522 if (stream == NULL
7523 || sink_metadata == NULL
7524 || sink_metadata->tracks == NULL) {
7525 return;
7526 }
7527
7528 int error = 0;
7529 struct stream_in *in = (struct stream_in *)stream;
7530 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007531 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007532 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007533
7534 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007535
7536 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007537 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007538
7539 lock_input_stream(in);
7540 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007541 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007542
Zhou Song62ea0282020-03-22 19:53:01 +08007543 is_ha_usecase = adev->ha_proxy_enable ?
7544 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7545 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7546 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007547 && adev->voice_tx_output != NULL) {
7548 /* Use the rx device from afe-proxy record to route voice call because
7549 there is no routing if tx device is on primary hal and rx device
7550 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007551 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007552
7553 if (!voice_is_call_state_active(adev)) {
7554 if (adev->mode == AUDIO_MODE_IN_CALL) {
7555 adev->current_call_output = adev->voice_tx_output;
7556 error = voice_start_call(adev);
7557 if (error != 0)
7558 ALOGE("%s: start voice call failed %d", __func__, error);
7559 }
7560 } else {
7561 adev->current_call_output = adev->voice_tx_output;
7562 voice_update_devices_for_all_voice_usecases(adev);
7563 }
7564 }
7565
7566 pthread_mutex_unlock(&adev->lock);
7567 pthread_mutex_unlock(&in->lock);
7568}
7569
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307570int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007571 audio_io_handle_t handle,
7572 audio_devices_t devices,
7573 audio_output_flags_t flags,
7574 struct audio_config *config,
7575 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007576 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007577{
7578 struct audio_device *adev = (struct audio_device *)dev;
7579 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307580 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007581 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007582 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307583 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007584 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7585 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7586 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7587 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007588 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007589 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7590 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007591 bool force_haptic_path =
7592 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007593 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007594
kunleizdff872d2018-08-20 14:40:33 +08007595 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007596 is_usb_dev = false;
7597 devices = AUDIO_DEVICE_OUT_SPEAKER;
7598 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7599 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007600 if (config->format == AUDIO_FORMAT_DEFAULT)
7601 config->format = AUDIO_FORMAT_PCM_16_BIT;
7602 if (config->sample_rate == 0)
7603 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7604 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7605 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007606 }
7607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007608 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307609
Rahul Sharma99770982019-03-06 17:05:26 +05307610 pthread_mutex_lock(&adev->lock);
7611 if (out_get_stream(adev, handle) != NULL) {
7612 ALOGW("%s, output stream already opened", __func__);
7613 ret = -EEXIST;
7614 }
7615 pthread_mutex_unlock(&adev->lock);
7616 if (ret)
7617 return ret;
7618
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007619 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7620
Mingming Yin3a941d42016-02-17 18:08:05 -08007621 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007622 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7623 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307624
7625
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007626 if (!out) {
7627 return -ENOMEM;
7628 }
7629
Haynes Mathew George204045b2015-02-25 20:32:03 -08007630 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007631 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307632 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007633 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007634 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007636 if (devices == AUDIO_DEVICE_NONE)
7637 devices = AUDIO_DEVICE_OUT_SPEAKER;
7638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007639 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007640 list_init(&out->device_list);
7641 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007642 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007643 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007644 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307645 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307646 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7647 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7648 else
7649 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007650 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007651 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007652 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307653 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307654 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307655 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007656 out->hal_output_suspend_supported = 0;
7657 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307658 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307659 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307660 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007661 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007662
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307663 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307664 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007665 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7666
Aalique Grahame22e49102018-12-18 14:23:57 -08007667 if (direct_dev &&
7668 (audio_is_linear_pcm(out->format) ||
7669 config->format == AUDIO_FORMAT_DEFAULT) &&
7670 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7671 audio_format_t req_format = config->format;
7672 audio_channel_mask_t req_channel_mask = config->channel_mask;
7673 uint32_t req_sample_rate = config->sample_rate;
7674
7675 pthread_mutex_lock(&adev->lock);
7676 if (is_hdmi) {
7677 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7678 ret = read_hdmi_sink_caps(out);
7679 if (config->sample_rate == 0)
7680 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7681 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7682 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7683 if (config->format == AUDIO_FORMAT_DEFAULT)
7684 config->format = AUDIO_FORMAT_PCM_16_BIT;
7685 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007686 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7687 &config->format,
7688 &out->supported_formats[0],
7689 MAX_SUPPORTED_FORMATS,
7690 &config->channel_mask,
7691 &out->supported_channel_masks[0],
7692 MAX_SUPPORTED_CHANNEL_MASKS,
7693 &config->sample_rate,
7694 &out->supported_sample_rates[0],
7695 MAX_SUPPORTED_SAMPLE_RATES);
7696 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007697 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007698
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007699 pthread_mutex_unlock(&adev->lock);
7700 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007701 if (ret == -ENOSYS) {
7702 /* ignore and go with default */
7703 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007704 }
7705 // For MMAP NO IRQ, allow conversions in ADSP
7706 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7707 goto error_open;
7708 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007709 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007710 goto error_open;
7711 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007712
7713 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7714 config->sample_rate = req_sample_rate;
7715 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7716 config->channel_mask = req_channel_mask;
7717 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7718 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007719 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007720
7721 out->sample_rate = config->sample_rate;
7722 out->channel_mask = config->channel_mask;
7723 out->format = config->format;
7724 if (is_hdmi) {
7725 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7726 out->config = pcm_config_hdmi_multi;
7727 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7728 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7729 out->config = pcm_config_mmap_playback;
7730 out->stream.start = out_start;
7731 out->stream.stop = out_stop;
7732 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7733 out->stream.get_mmap_position = out_get_mmap_position;
7734 } else {
7735 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7736 out->config = pcm_config_hifi;
7737 }
7738
7739 out->config.rate = out->sample_rate;
7740 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7741 if (is_hdmi) {
7742 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7743 audio_bytes_per_sample(out->format));
7744 }
7745 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007746 }
7747
Derek Chenf6318be2017-06-12 17:16:24 -04007748 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007749 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007750 /* extract car audio stream index */
7751 out->car_audio_stream =
7752 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7753 if (out->car_audio_stream < 0) {
7754 ALOGE("%s: invalid car audio stream %x",
7755 __func__, out->car_audio_stream);
7756 ret = -EINVAL;
7757 goto error_open;
7758 }
Derek Chen5f67a942020-02-24 23:08:13 -08007759 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007760 }
7761
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007762 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007763 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007764 if (!voice_extn_is_compress_voip_supported()) {
7765 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7766 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007767 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7768 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007769 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7770 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007771 out->volume_l = INVALID_OUT_VOLUME;
7772 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007773
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007774 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007775 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007776 uint32_t channel_count =
7777 audio_channel_count_from_out_mask(out->channel_mask);
7778 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7779 out->sample_rate, out->format,
7780 channel_count, false);
7781 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7782 if (frame_size != 0)
7783 out->config.period_size = buffer_size / frame_size;
7784 else
7785 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007786 }
7787 } else {
7788 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7789 voice_extn_compress_voip_is_active(out->dev)) &&
7790 (voice_extn_compress_voip_is_config_supported(config))) {
7791 ret = voice_extn_compress_voip_open_output_stream(out);
7792 if (ret != 0) {
7793 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7794 __func__, ret);
7795 goto error_open;
7796 }
Sujin Panicker19027262019-09-16 18:28:06 +05307797 } else {
7798 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7799 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007800 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007801 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007802 } else if (audio_is_linear_pcm(out->format) &&
7803 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7804 out->channel_mask = config->channel_mask;
7805 out->sample_rate = config->sample_rate;
7806 out->format = config->format;
7807 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7808 // does this change?
7809 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7810 out->config.rate = config->sample_rate;
7811 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7812 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7813 audio_bytes_per_sample(config->format));
7814 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007815 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307816 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307817 pthread_mutex_lock(&adev->lock);
7818 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7819 pthread_mutex_unlock(&adev->lock);
7820
7821 // reject offload during card offline to allow
7822 // fallback to s/w paths
7823 if (offline) {
7824 ret = -ENODEV;
7825 goto error_open;
7826 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007827
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007828 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7829 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7830 ALOGE("%s: Unsupported Offload information", __func__);
7831 ret = -EINVAL;
7832 goto error_open;
7833 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007834
Atul Khare3fa6e542017-08-09 00:56:17 +05307835 if (config->offload_info.format == 0)
7836 config->offload_info.format = config->format;
7837 if (config->offload_info.sample_rate == 0)
7838 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007839
Mingming Yin90310102013-11-13 16:57:00 -08007840 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307841 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007842 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007843 ret = -EINVAL;
7844 goto error_open;
7845 }
7846
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007847 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7848 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7849 (audio_extn_passthru_is_passthrough_stream(out)) &&
7850 !((config->sample_rate == 48000) ||
7851 (config->sample_rate == 96000) ||
7852 (config->sample_rate == 192000))) {
7853 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7854 __func__, config->sample_rate, config->offload_info.format);
7855 ret = -EINVAL;
7856 goto error_open;
7857 }
7858
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007859 out->compr_config.codec = (struct snd_codec *)
7860 calloc(1, sizeof(struct snd_codec));
7861
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007862 if (!out->compr_config.codec) {
7863 ret = -ENOMEM;
7864 goto error_open;
7865 }
7866
Dhananjay Kumarac341582017-02-23 23:42:25 +05307867 out->stream.pause = out_pause;
7868 out->stream.resume = out_resume;
7869 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307870 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307871 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007872 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307873 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007874 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307875 } else {
7876 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7877 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007878 }
vivek mehta446c3962015-09-14 10:57:35 -07007879
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307880 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7881 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007882#ifdef AUDIO_GKI_ENABLED
7883 /* out->compr_config.codec->reserved[1] is for flags */
7884 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7885#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307886 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007887#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307888 }
7889
vivek mehta446c3962015-09-14 10:57:35 -07007890 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007891 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007892 config->format == 0 && config->sample_rate == 0 &&
7893 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007894 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007895 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7896 } else {
7897 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7898 ret = -EEXIST;
7899 goto error_open;
7900 }
vivek mehta446c3962015-09-14 10:57:35 -07007901 }
7902
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007903 if (config->offload_info.channel_mask)
7904 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007905 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007906 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007907 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007908 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307909 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007910 ret = -EINVAL;
7911 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007912 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007913
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007914 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007915 out->sample_rate = config->offload_info.sample_rate;
7916
Mingming Yin3ee55c62014-08-04 14:23:35 -07007917 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007918
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307919 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307920 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307921 audio_extn_dolby_send_ddp_endp_params(adev);
7922 audio_extn_dolby_set_dmid(adev);
7923 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007924
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007925 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007926 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007927 out->compr_config.codec->bit_rate =
7928 config->offload_info.bit_rate;
7929 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307930 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007931 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307932 /* Update bit width only for non passthrough usecases.
7933 * For passthrough usecases, the output will always be opened @16 bit
7934 */
7935 if (!audio_extn_passthru_is_passthrough_stream(out))
7936 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307937
7938 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007939#ifdef AUDIO_GKI_ENABLED
7940 /* out->compr_config.codec->reserved[1] is for flags */
7941 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7942 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7943#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307944 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7945 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007946#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307947
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007948 /*TODO: Do we need to change it for passthrough */
7949 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007950
Manish Dewangana6fc5442015-08-24 20:30:31 +05307951 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7952 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307953 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307954 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307955 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7956 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307957
7958 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7959 AUDIO_FORMAT_PCM) {
7960
7961 /*Based on platform support, configure appropriate alsa format for corresponding
7962 *hal input format.
7963 */
7964 out->compr_config.codec->format = hal_format_to_alsa(
7965 config->offload_info.format);
7966
Ashish Jain83a6cc22016-06-28 14:34:17 +05307967 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307968 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307969 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307970
Dhananjay Kumarac341582017-02-23 23:42:25 +05307971 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307972 *hal input format and alsa format might differ based on platform support.
7973 */
7974 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307975 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307976
7977 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7978
Deeraj Soman93155a62019-09-30 19:00:37 +05307979 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7980 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7981 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7982 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7983 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307984
Ashish Jainf1eaa582016-05-23 20:54:24 +05307985 /* Check if alsa session is configured with the same format as HAL input format,
7986 * if not then derive correct fragment size needed to accomodate the
7987 * conversion of HAL input format to alsa format.
7988 */
7989 audio_extn_utils_update_direct_pcm_fragment_size(out);
7990
7991 /*if hal input and output fragment size is different this indicates HAL input format is
7992 *not same as the alsa format
7993 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307994 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307995 /*Allocate a buffer to convert input data to the alsa configured format.
7996 *size of convert buffer is equal to the size required to hold one fragment size
7997 *worth of pcm data, this is because flinger does not write more than fragment_size
7998 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307999 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8000 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308001 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8002 ret = -ENOMEM;
8003 goto error_open;
8004 }
8005 }
8006 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8007 out->compr_config.fragment_size =
8008 audio_extn_passthru_get_buffer_size(&config->offload_info);
8009 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8010 } else {
8011 out->compr_config.fragment_size =
8012 platform_get_compress_offload_buffer_size(&config->offload_info);
8013 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8014 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008015
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308016 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8017 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8018 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07008019 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308020 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008021
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308022 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8023 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8024 }
8025
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008026 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8027 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008028
Manish Dewangan69426c82017-01-30 17:35:36 +05308029 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8030 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8031 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8032 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8033 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8034 } else {
8035 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8036 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008037
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308038 memset(&out->channel_map_param, 0,
8039 sizeof(struct audio_out_channel_map_param));
8040
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008041 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308042 out->send_next_track_params = false;
8043 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008044 out->offload_state = OFFLOAD_STATE_IDLE;
8045 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008046 out->writeAt.tv_sec = 0;
8047 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008048
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008049 audio_extn_dts_create_state_notifier_node(out->usecase);
8050
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008051 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8052 __func__, config->offload_info.version,
8053 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308054
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308055 /* Check if DSD audio format is supported in codec
8056 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308057 */
8058
8059 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308060 (!platform_check_codec_dsd_support(adev->platform) ||
8061 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308062 ret = -EINVAL;
8063 goto error_open;
8064 }
8065
Ashish Jain5106d362016-05-11 19:23:33 +05308066 /* Disable gapless if any of the following is true
8067 * passthrough playback
8068 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308069 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308070 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308071 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308072 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008073 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308074 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308075 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308076 check_and_set_gapless_mode(adev, false);
8077 } else
8078 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008079
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308080 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008081 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8082 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308083 if (config->format == AUDIO_FORMAT_DSD) {
8084 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008085#ifdef AUDIO_GKI_ENABLED
8086 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8087 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8088#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308089 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008090#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308091 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008092
8093 create_offload_callback_thread(out);
8094
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008095 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008096 switch (config->sample_rate) {
8097 case 0:
8098 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8099 break;
8100 case 8000:
8101 case 16000:
8102 case 48000:
8103 out->sample_rate = config->sample_rate;
8104 break;
8105 default:
8106 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8107 config->sample_rate);
8108 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8109 ret = -EINVAL;
8110 goto error_open;
8111 }
8112 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8113 switch (config->channel_mask) {
8114 case AUDIO_CHANNEL_NONE:
8115 case AUDIO_CHANNEL_OUT_STEREO:
8116 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8117 break;
8118 default:
8119 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8120 config->channel_mask);
8121 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8122 ret = -EINVAL;
8123 goto error_open;
8124 }
8125 switch (config->format) {
8126 case AUDIO_FORMAT_DEFAULT:
8127 case AUDIO_FORMAT_PCM_16_BIT:
8128 out->format = AUDIO_FORMAT_PCM_16_BIT;
8129 break;
8130 default:
8131 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8132 config->format);
8133 config->format = AUDIO_FORMAT_PCM_16_BIT;
8134 ret = -EINVAL;
8135 goto error_open;
8136 }
8137
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308138 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008139 if (ret != 0) {
8140 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008141 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008142 goto error_open;
8143 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008144 } else if (is_single_device_type_equal(&out->device_list,
8145 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008146 switch (config->sample_rate) {
8147 case 0:
8148 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8149 break;
8150 case 8000:
8151 case 16000:
8152 case 48000:
8153 out->sample_rate = config->sample_rate;
8154 break;
8155 default:
8156 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8157 config->sample_rate);
8158 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8159 ret = -EINVAL;
8160 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008161 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008162 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8163 switch (config->channel_mask) {
8164 case AUDIO_CHANNEL_NONE:
8165 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8166 break;
8167 case AUDIO_CHANNEL_OUT_STEREO:
8168 out->channel_mask = config->channel_mask;
8169 break;
8170 default:
8171 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8172 config->channel_mask);
8173 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8174 ret = -EINVAL;
8175 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008176 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008177 switch (config->format) {
8178 case AUDIO_FORMAT_DEFAULT:
8179 out->format = AUDIO_FORMAT_PCM_16_BIT;
8180 break;
8181 case AUDIO_FORMAT_PCM_16_BIT:
8182 out->format = config->format;
8183 break;
8184 default:
8185 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8186 config->format);
8187 config->format = AUDIO_FORMAT_PCM_16_BIT;
8188 ret = -EINVAL;
8189 break;
8190 }
8191 if (ret != 0)
8192 goto error_open;
8193
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008194 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8195 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008196 out->config.rate = out->sample_rate;
8197 out->config.channels =
8198 audio_channel_count_from_out_mask(out->channel_mask);
8199 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008200 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008201 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308202 unsigned int channels = 0;
8203 /*Update config params to default if not set by the caller*/
8204 if (config->sample_rate == 0)
8205 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8206 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8207 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8208 if (config->format == AUDIO_FORMAT_DEFAULT)
8209 config->format = AUDIO_FORMAT_PCM_16_BIT;
8210
8211 channels = audio_channel_count_from_out_mask(out->channel_mask);
8212
Varun Balaraje49253e2017-07-06 19:48:56 +05308213 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8214 out->usecase = get_interactive_usecase(adev);
8215 out->config = pcm_config_low_latency;
8216 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308217 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008218 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8219 out->flags);
8220 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008221 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8222 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8223 out->config = pcm_config_mmap_playback;
8224 out->stream.start = out_start;
8225 out->stream.stop = out_stop;
8226 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8227 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308228 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8229 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008230 out->hal_output_suspend_supported =
8231 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8232 out->dynamic_pm_qos_config_supported =
8233 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8234 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008235 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8236 } else {
8237 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8238 //the mixer path will be a string similar to "low-latency-playback resume"
8239 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8240 strlcat(out->pm_qos_mixer_path,
8241 " resume", MAX_MIXER_PATH_LEN);
8242 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8243 out->pm_qos_mixer_path);
8244 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308245 out->config = pcm_config_low_latency;
8246 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8247 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8248 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308249 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8250 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8251 if (out->config.period_size <= 0) {
8252 ALOGE("Invalid configuration period size is not valid");
8253 ret = -EINVAL;
8254 goto error_open;
8255 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008256 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8257 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8258 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008259 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8260 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8261 out->config = pcm_config_haptics_audio;
8262 if (force_haptic_path)
8263 adev->haptics_config = pcm_config_haptics_audio;
8264 else
8265 adev->haptics_config = pcm_config_haptics;
8266
Meng Wangd08ce322020-04-02 08:59:20 +08008267 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008268 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8269
8270 if (force_haptic_path) {
8271 out->config.channels = 1;
8272 adev->haptics_config.channels = 1;
8273 } else
8274 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 -08008275 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008276 ret = audio_extn_auto_hal_open_output_stream(out);
8277 if (ret) {
8278 ALOGE("%s: Failed to open output stream for bus device", __func__);
8279 ret = -EINVAL;
8280 goto error_open;
8281 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308282 } else {
8283 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008284 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8285 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308286 }
8287 out->hal_ip_format = format = out->format;
8288 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8289 out->hal_op_format = pcm_format_to_hal(out->config.format);
8290 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8291 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008292 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308293 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308294 if (out->hal_ip_format != out->hal_op_format) {
8295 uint32_t buffer_size = out->config.period_size *
8296 format_to_bitwidth_table[out->hal_op_format] *
8297 out->config.channels;
8298 out->convert_buffer = calloc(1, buffer_size);
8299 if (out->convert_buffer == NULL){
8300 ALOGE("Allocation failed for convert buffer for size %d",
8301 out->compr_config.fragment_size);
8302 ret = -ENOMEM;
8303 goto error_open;
8304 }
8305 ALOGD("Convert buffer allocated of size %d", buffer_size);
8306 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008307 }
8308
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008309 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8310 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308311
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008312 /* TODO remove this hardcoding and check why width is zero*/
8313 if (out->bit_width == 0)
8314 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308315 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008316 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008317 &out->device_list, out->flags,
8318 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308319 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308320 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008321 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008322 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8323 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008324 if(adev->primary_output == NULL)
8325 adev->primary_output = out;
8326 else {
8327 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008328 ret = -EEXIST;
8329 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008330 }
8331 }
8332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008333 /* Check if this usecase is already existing */
8334 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008335 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8336 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008337 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008338 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008339 ret = -EEXIST;
8340 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008341 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008342
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008343 pthread_mutex_unlock(&adev->lock);
8344
8345 out->stream.common.get_sample_rate = out_get_sample_rate;
8346 out->stream.common.set_sample_rate = out_set_sample_rate;
8347 out->stream.common.get_buffer_size = out_get_buffer_size;
8348 out->stream.common.get_channels = out_get_channels;
8349 out->stream.common.get_format = out_get_format;
8350 out->stream.common.set_format = out_set_format;
8351 out->stream.common.standby = out_standby;
8352 out->stream.common.dump = out_dump;
8353 out->stream.common.set_parameters = out_set_parameters;
8354 out->stream.common.get_parameters = out_get_parameters;
8355 out->stream.common.add_audio_effect = out_add_audio_effect;
8356 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8357 out->stream.get_latency = out_get_latency;
8358 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008359#ifdef NO_AUDIO_OUT
8360 out->stream.write = out_write_for_no_output;
8361#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008362 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008363#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008364 out->stream.get_render_position = out_get_render_position;
8365 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008366 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008367
Haynes Mathew George16081042017-05-31 17:16:49 -07008368 if (out->realtime)
8369 out->af_period_multiplier = af_period_multiplier;
8370 else
8371 out->af_period_multiplier = 1;
8372
Andy Hunga1f48fa2019-07-01 18:14:53 -07008373 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008375 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008376 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008377 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008378
8379 config->format = out->stream.common.get_format(&out->stream.common);
8380 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8381 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308382 register_format(out->format, out->supported_formats);
8383 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8384 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008385
Aalique Grahame22e49102018-12-18 14:23:57 -08008386 out->error_log = error_log_create(
8387 ERROR_LOG_ENTRIES,
8388 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8389
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308390 /*
8391 By locking output stream before registering, we allow the callback
8392 to update stream's state only after stream's initial state is set to
8393 adev state.
8394 */
8395 lock_output_stream(out);
8396 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8397 pthread_mutex_lock(&adev->lock);
8398 out->card_status = adev->card_status;
8399 pthread_mutex_unlock(&adev->lock);
8400 pthread_mutex_unlock(&out->lock);
8401
Aalique Grahame22e49102018-12-18 14:23:57 -08008402 stream_app_type_cfg_init(&out->app_type_cfg);
8403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008404 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308405 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008406 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008407
8408 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8409 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8410 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008411 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308412 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008413 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008414 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308415 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8416 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008417 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8418 out->usecase, PCM_PLAYBACK);
8419 hdlr_stream_cfg.flags = out->flags;
8420 hdlr_stream_cfg.type = PCM_PLAYBACK;
8421 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8422 &hdlr_stream_cfg);
8423 if (ret) {
8424 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8425 out->adsp_hdlr_stream_handle = NULL;
8426 }
8427 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308428 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8429 is_direct_passthough, false);
8430 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8431 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008432 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008433 if (ret < 0) {
8434 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8435 out->ip_hdlr_handle = NULL;
8436 }
8437 }
Derek Chenf939fb72018-11-13 13:34:41 -08008438
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008439 ret = io_streams_map_insert(adev, &out->stream.common,
8440 out->handle, AUDIO_PATCH_HANDLE_NONE);
8441 if (ret != 0)
8442 goto error_open;
8443
Derek Chenf939fb72018-11-13 13:34:41 -08008444 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8445 calloc(1, sizeof(streams_output_ctxt_t));
8446 if (out_ctxt == NULL) {
8447 ALOGE("%s fail to allocate output ctxt", __func__);
8448 ret = -ENOMEM;
8449 goto error_open;
8450 }
8451 out_ctxt->output = out;
8452
8453 pthread_mutex_lock(&adev->lock);
8454 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8455 pthread_mutex_unlock(&adev->lock);
8456
Eric Laurent994a6932013-07-17 11:51:42 -07008457 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008458 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008459
8460error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308461 if (out->convert_buffer)
8462 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008463 free(out);
8464 *stream_out = NULL;
8465 ALOGD("%s: exit: ret %d", __func__, ret);
8466 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008467}
8468
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308469void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008470 struct audio_stream_out *stream)
8471{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008472 struct stream_out *out = (struct stream_out *)stream;
8473 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008474 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008475
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008476 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308477
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008478 io_streams_map_remove(adev, out->handle);
8479
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308480 // must deregister from sndmonitor first to prevent races
8481 // between the callback and close_stream
8482 audio_extn_snd_mon_unregister_listener(out);
8483
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008484 /* close adsp hdrl session before standby */
8485 if (out->adsp_hdlr_stream_handle) {
8486 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8487 if (ret)
8488 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8489 out->adsp_hdlr_stream_handle = NULL;
8490 }
8491
Manish Dewangan21a850a2017-08-14 12:03:55 +05308492 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008493 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8494 out->ip_hdlr_handle = NULL;
8495 }
8496
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008497 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308498 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008499 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308500 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308501 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008502 if(ret != 0)
8503 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8504 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008505 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008506 out_standby(&stream->common);
8507
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008508 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008509 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008510 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008511 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008512 if (out->compr_config.codec != NULL)
8513 free(out->compr_config.codec);
8514 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008515
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308516 out->a2dp_compress_mute = false;
8517
Varun Balaraje49253e2017-07-06 19:48:56 +05308518 if (is_interactive_usecase(out->usecase))
8519 free_interactive_usecase(adev, out->usecase);
8520
Ashish Jain83a6cc22016-06-28 14:34:17 +05308521 if (out->convert_buffer != NULL) {
8522 free(out->convert_buffer);
8523 out->convert_buffer = NULL;
8524 }
8525
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008526 if (adev->voice_tx_output == out)
8527 adev->voice_tx_output = NULL;
8528
Aalique Grahame22e49102018-12-18 14:23:57 -08008529 error_log_destroy(out->error_log);
8530 out->error_log = NULL;
8531
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308532 if (adev->primary_output == out)
8533 adev->primary_output = NULL;
8534
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008535 pthread_cond_destroy(&out->cond);
8536 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008537
8538 pthread_mutex_lock(&adev->lock);
8539 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8540 if (out_ctxt != NULL) {
8541 list_remove(&out_ctxt->list);
8542 free(out_ctxt);
8543 } else {
8544 ALOGW("%s, output stream already closed", __func__);
8545 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008546 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008547 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008548 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008549}
8550
8551static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8552{
8553 struct audio_device *adev = (struct audio_device *)dev;
8554 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008555 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008556 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008557 int ret;
8558 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008559 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008560 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008561 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008562
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008563 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008564 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008565
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308566 if (!parms)
8567 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308568
Derek Chen6f293672019-04-01 01:40:24 -07008569 /* notify adev and input/output streams on the snd card status */
8570 adev_snd_mon_cb((void *)adev, parms);
8571
8572 list_for_each(node, &adev->active_outputs_list) {
8573 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8574 streams_output_ctxt_t,
8575 list);
8576 out_snd_mon_cb((void *)out_ctxt->output, parms);
8577 }
8578
8579 list_for_each(node, &adev->active_inputs_list) {
8580 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8581 streams_input_ctxt_t,
8582 list);
8583 in_snd_mon_cb((void *)in_ctxt->input, parms);
8584 }
8585
Zhou Songd6d71752019-05-21 18:08:51 +08008586 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308587 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8588 if (ret >= 0) {
8589 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008590 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308591 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008592 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308593 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008594 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008595 }
8596 }
8597
8598 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8599 if (ret>=0) {
8600 if (!strncmp(value, "false", 5) &&
8601 audio_extn_a2dp_source_is_suspended()) {
8602 struct audio_usecase *usecase;
8603 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008604 list_for_each(node, &adev->usecase_list) {
8605 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008606 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008607 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008608 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008609 reassign_device_list(&usecase->stream.in->device_list,
8610 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008611 select_devices(adev, usecase->id);
8612 }
Zhou Songd6d71752019-05-21 18:08:51 +08008613 }
8614 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308615 }
8616
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008617 status = voice_set_parameters(adev, parms);
8618 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008619 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008620
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008621 status = platform_set_parameters(adev->platform, parms);
8622 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008623 goto done;
8624
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008625 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8626 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008627 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008628 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8629 adev->bluetooth_nrec = true;
8630 else
8631 adev->bluetooth_nrec = false;
8632 }
8633
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008634 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8635 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008636 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8637 adev->screen_off = false;
8638 else
8639 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008640 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008641 }
8642
Eric Laurent4b084132018-10-19 17:33:43 -07008643 ret = str_parms_get_int(parms, "rotation", &val);
8644 if (ret >= 0) {
8645 bool reverse_speakers = false;
8646 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8647 switch (val) {
8648 // FIXME: note that the code below assumes that the speakers are in the correct placement
8649 // relative to the user when the device is rotated 90deg from its default rotation. This
8650 // assumption is device-specific, not platform-specific like this code.
8651 case 270:
8652 reverse_speakers = true;
8653 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8654 break;
8655 case 0:
8656 case 180:
8657 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8658 break;
8659 case 90:
8660 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8661 break;
8662 default:
8663 ALOGE("%s: unexpected rotation of %d", __func__, val);
8664 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008665 }
Eric Laurent4b084132018-10-19 17:33:43 -07008666 if (status == 0) {
8667 // check and set swap
8668 // - check if orientation changed and speaker active
8669 // - set rotation and cache the rotation value
8670 adev->camera_orientation =
8671 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8672 if (!audio_extn_is_maxx_audio_enabled())
8673 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8674 }
8675 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008676
Mingming Yin514a8bc2014-07-29 15:22:21 -07008677 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8678 if (ret >= 0) {
8679 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8680 adev->bt_wb_speech_enabled = true;
8681 else
8682 adev->bt_wb_speech_enabled = false;
8683 }
8684
Zhou Song12c29502019-03-16 10:37:18 +08008685 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8686 if (ret >= 0) {
8687 val = atoi(value);
8688 adev->swb_speech_mode = val;
8689 }
8690
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008691 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8692 if (ret >= 0) {
8693 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308694 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008695 if (audio_is_output_device(val) &&
8696 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008697 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008698 platform_get_controller_stream_from_params(parms, &controller, &stream);
8699 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8700 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008701 if (ret < 0) {
8702 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308703 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008704 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008705 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308706 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008707 /*
8708 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8709 * Per AudioPolicyManager, USB device is higher priority than WFD.
8710 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8711 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8712 * starting voice call on USB
8713 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008714 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308715 if (ret >= 0)
8716 audio_extn_usb_add_device(device, atoi(value));
8717
Zhou Song6f862822017-11-06 17:27:57 +08008718 if (!audio_extn_usb_is_tunnel_supported()) {
8719 ALOGV("detected USB connect .. disable proxy");
8720 adev->allow_afe_proxy_usage = false;
8721 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008722 }
8723 }
8724
8725 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8726 if (ret >= 0) {
8727 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308728 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008729 /*
8730 * The HDMI / Displayport disconnect handling has been moved to
8731 * audio extension to ensure that its parameters are not
8732 * invalidated prior to updating sysfs of the disconnect event
8733 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8734 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308735 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008736 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308737 if (ret >= 0)
8738 audio_extn_usb_remove_device(device, atoi(value));
8739
Zhou Song6f862822017-11-06 17:27:57 +08008740 if (!audio_extn_usb_is_tunnel_supported()) {
8741 ALOGV("detected USB disconnect .. enable proxy");
8742 adev->allow_afe_proxy_usage = true;
8743 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008744 }
8745 }
8746
Aalique Grahame22e49102018-12-18 14:23:57 -08008747 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008748 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008749
8750 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008751 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308752 struct audio_usecase *usecase;
8753 struct listnode *node;
8754 list_for_each(node, &adev->usecase_list) {
8755 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308756 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008757 is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308758 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008759 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308760 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008761 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308762 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308763 ALOGD("Switching to speaker and muting the stream before select_devices");
8764 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308765 //force device switch to re configure encoder
8766 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308767 ALOGD("Unmuting the stream after select_devices");
8768 usecase->stream.out->a2dp_compress_mute = false;
8769 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 +05308770 audio_extn_a2dp_set_handoff_mode(false);
8771 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308772 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308773 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8774 usecase->stream.out->a2dp_compress_mute) {
8775 pthread_mutex_unlock(&adev->lock);
8776 lock_output_stream(usecase->stream.out);
8777 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008778 reassign_device_list(&usecase->stream.out->device_list,
8779 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308780 check_a2dp_restore_l(adev, usecase->stream.out, true);
8781 pthread_mutex_unlock(&usecase->stream.out->lock);
8782 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308783 }
8784 }
8785 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008786
8787 //handle vr audio setparam
8788 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8789 value, sizeof(value));
8790 if (ret >= 0) {
8791 ALOGI("Setting vr mode to be %s", value);
8792 if (!strncmp(value, "true", 4)) {
8793 adev->vr_audio_mode_enabled = true;
8794 ALOGI("Setting vr mode to true");
8795 } else if (!strncmp(value, "false", 5)) {
8796 adev->vr_audio_mode_enabled = false;
8797 ALOGI("Setting vr mode to false");
8798 } else {
8799 ALOGI("wrong vr mode set");
8800 }
8801 }
8802
Eric Laurent4b084132018-10-19 17:33:43 -07008803 //FIXME: to be replaced by proper video capture properties API
8804 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8805 if (ret >= 0) {
8806 int camera_facing = CAMERA_FACING_BACK;
8807 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8808 camera_facing = CAMERA_FACING_FRONT;
8809 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8810 camera_facing = CAMERA_FACING_BACK;
8811 else {
8812 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8813 goto done;
8814 }
8815 adev->camera_orientation =
8816 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8817 struct audio_usecase *usecase;
8818 struct listnode *node;
8819 list_for_each(node, &adev->usecase_list) {
8820 usecase = node_to_item(node, struct audio_usecase, list);
8821 struct stream_in *in = usecase->stream.in;
8822 if (usecase->type == PCM_CAPTURE && in != NULL &&
8823 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8824 select_devices(adev, in->usecase);
8825 }
8826 }
8827 }
8828
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308829 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008830done:
8831 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008832 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308833error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008834 ALOGV("%s: exit with code(%d)", __func__, status);
8835 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008836}
8837
8838static char* adev_get_parameters(const struct audio_hw_device *dev,
8839 const char *keys)
8840{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308841 ALOGD("%s:%s", __func__, keys);
8842
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008843 struct audio_device *adev = (struct audio_device *)dev;
8844 struct str_parms *reply = str_parms_create();
8845 struct str_parms *query = str_parms_create_str(keys);
8846 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308847 char value[256] = {0};
8848 int ret = 0;
8849
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008850 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008851 if (reply) {
8852 str_parms_destroy(reply);
8853 }
8854 if (query) {
8855 str_parms_destroy(query);
8856 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008857 ALOGE("adev_get_parameters: failed to create query or reply");
8858 return NULL;
8859 }
8860
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008861 //handle vr audio getparam
8862
8863 ret = str_parms_get_str(query,
8864 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8865 value, sizeof(value));
8866
8867 if (ret >= 0) {
8868 bool vr_audio_enabled = false;
8869 pthread_mutex_lock(&adev->lock);
8870 vr_audio_enabled = adev->vr_audio_mode_enabled;
8871 pthread_mutex_unlock(&adev->lock);
8872
8873 ALOGI("getting vr mode to %d", vr_audio_enabled);
8874
8875 if (vr_audio_enabled) {
8876 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8877 "true");
8878 goto exit;
8879 } else {
8880 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8881 "false");
8882 goto exit;
8883 }
8884 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008885
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008886 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008887 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008888 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008889 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008890 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08008891 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308892 pthread_mutex_unlock(&adev->lock);
8893
Naresh Tannirud7205b62014-06-20 02:54:48 +05308894exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008895 str = str_parms_to_str(reply);
8896 str_parms_destroy(query);
8897 str_parms_destroy(reply);
8898
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308899 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008900 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008901}
8902
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008903static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008904{
8905 return 0;
8906}
8907
8908static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8909{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008910 int ret;
8911 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008912
8913 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8914
Haynes Mathew George5191a852013-09-11 14:19:36 -07008915 pthread_mutex_lock(&adev->lock);
8916 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008917 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008918 pthread_mutex_unlock(&adev->lock);
8919 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008920}
8921
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008922static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8923 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008924{
8925 return -ENOSYS;
8926}
8927
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008928static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8929 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008930{
8931 return -ENOSYS;
8932}
8933
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008934static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8935 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008936{
8937 return -ENOSYS;
8938}
8939
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008940static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8941 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008942{
8943 return -ENOSYS;
8944}
8945
8946static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8947{
8948 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008949 struct listnode *node;
8950 struct audio_usecase *usecase = NULL;
8951 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008953 pthread_mutex_lock(&adev->lock);
8954 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05308955 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
8956 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008957 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05308958 if( mode == AUDIO_MODE_CALL_SCREEN ){
8959 adev->current_call_output = adev->primary_output;
8960 voice_start_call(adev);
8961 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008962 (mode == AUDIO_MODE_NORMAL ||
8963 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008964 list_for_each(node, &adev->usecase_list) {
8965 usecase = node_to_item(node, struct audio_usecase, list);
8966 if (usecase->type == VOICE_CALL)
8967 break;
8968 }
8969 if (usecase &&
8970 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8971 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8972 true);
8973 if (ret != 0) {
8974 /* default service interval was successfully updated,
8975 reopen USB backend with new service interval */
8976 check_usecases_codec_backend(adev,
8977 usecase,
8978 usecase->out_snd_device);
8979 }
8980 }
8981
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008982 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008983 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008984 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008985 // restore device for other active usecases after stop call
8986 list_for_each(node, &adev->usecase_list) {
8987 usecase = node_to_item(node, struct audio_usecase, list);
8988 select_devices(adev, usecase->id);
8989 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008990 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008991 }
8992 pthread_mutex_unlock(&adev->lock);
8993 return 0;
8994}
8995
8996static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8997{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008998 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008999 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009000
9001 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009002 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009003 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009004
Derek Chend2530072014-11-24 12:39:14 -08009005 if (adev->ext_hw_plugin)
9006 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009007
9008 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009009 pthread_mutex_unlock(&adev->lock);
9010
9011 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009012}
9013
9014static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9015{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009016 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009017 return 0;
9018}
9019
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009020static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009021 const struct audio_config *config)
9022{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009023 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009024
Aalique Grahame22e49102018-12-18 14:23:57 -08009025 /* Don't know if USB HIFI in this context so use true to be conservative */
9026 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9027 true /*is_usb_hifi */) != 0)
9028 return 0;
9029
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009030 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9031 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009032}
9033
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009034static bool adev_input_allow_hifi_record(struct audio_device *adev,
9035 audio_devices_t devices,
9036 audio_input_flags_t flags,
9037 audio_source_t source) {
9038 const bool allowed = true;
9039
9040 if (!audio_is_usb_in_device(devices))
9041 return !allowed;
9042
9043 switch (flags) {
9044 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009045 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009046 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9047 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009048 default:
9049 return !allowed;
9050 }
9051
9052 switch (source) {
9053 case AUDIO_SOURCE_DEFAULT:
9054 case AUDIO_SOURCE_MIC:
9055 case AUDIO_SOURCE_UNPROCESSED:
9056 break;
9057 default:
9058 return !allowed;
9059 }
9060
9061 switch (adev->mode) {
9062 case 0:
9063 break;
9064 default:
9065 return !allowed;
9066 }
9067
9068 return allowed;
9069}
9070
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009071static int adev_update_voice_comm_input_stream(struct stream_in *in,
9072 struct audio_config *config)
9073{
9074 bool valid_rate = (config->sample_rate == 8000 ||
9075 config->sample_rate == 16000 ||
9076 config->sample_rate == 32000 ||
9077 config->sample_rate == 48000);
9078 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9079
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009080 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009081 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009082 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9083 in->config = default_pcm_config_voip_copp;
9084 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9085 DEFAULT_VOIP_BUF_DURATION_MS,
9086 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009087 } else {
9088 ALOGW("%s No valid input in voip, use defaults"
9089 "sample rate %u, channel mask 0x%X",
9090 __func__, config->sample_rate, in->channel_mask);
9091 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009092 in->config.rate = config->sample_rate;
9093 in->sample_rate = config->sample_rate;
9094 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009095 //XXX needed for voice_extn_compress_voip_open_input_stream
9096 in->config.rate = config->sample_rate;
9097 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309098 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009099 voice_extn_compress_voip_is_active(in->dev)) &&
9100 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9101 valid_rate && valid_ch) {
9102 voice_extn_compress_voip_open_input_stream(in);
9103 // update rate entries to match config from AF
9104 in->config.rate = config->sample_rate;
9105 in->sample_rate = config->sample_rate;
9106 } else {
9107 ALOGW("%s compress voip not active, use defaults", __func__);
9108 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009109 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009110 return 0;
9111}
9112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009113static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009114 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009115 audio_devices_t devices,
9116 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009117 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309118 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009119 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009120 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009121{
9122 struct audio_device *adev = (struct audio_device *)dev;
9123 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009124 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009125 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009126 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309127 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009128 bool is_usb_dev = audio_is_usb_in_device(devices);
9129 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9130 devices,
9131 flags,
9132 source);
Andy Hung94320602018-10-29 18:31:12 -07009133 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9134 " sample_rate %u, channel_mask %#x, format %#x",
9135 __func__, flags, is_usb_dev, may_use_hifi_record,
9136 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309137
kunleizdff872d2018-08-20 14:40:33 +08009138 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009139 is_usb_dev = false;
9140 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9141 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9142 __func__, devices);
9143 }
9144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009145 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009146
9147 if (!(is_usb_dev && may_use_hifi_record)) {
9148 if (config->sample_rate == 0)
9149 config->sample_rate = 48000;
9150 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9151 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9152 if (config->format == AUDIO_FORMAT_DEFAULT)
9153 config->format = AUDIO_FORMAT_PCM_16_BIT;
9154
9155 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9156
Aalique Grahame22e49102018-12-18 14:23:57 -08009157 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9158 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009159 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309160 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009161
Rahul Sharma99770982019-03-06 17:05:26 +05309162 pthread_mutex_lock(&adev->lock);
9163 if (in_get_stream(adev, handle) != NULL) {
9164 ALOGW("%s, input stream already opened", __func__);
9165 ret = -EEXIST;
9166 }
9167 pthread_mutex_unlock(&adev->lock);
9168 if (ret)
9169 return ret;
9170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009171 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009172
9173 if (!in) {
9174 ALOGE("failed to allocate input stream");
9175 return -ENOMEM;
9176 }
9177
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309178 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309179 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9180 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009181 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009182 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009183
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009184 in->stream.common.get_sample_rate = in_get_sample_rate;
9185 in->stream.common.set_sample_rate = in_set_sample_rate;
9186 in->stream.common.get_buffer_size = in_get_buffer_size;
9187 in->stream.common.get_channels = in_get_channels;
9188 in->stream.common.get_format = in_get_format;
9189 in->stream.common.set_format = in_set_format;
9190 in->stream.common.standby = in_standby;
9191 in->stream.common.dump = in_dump;
9192 in->stream.common.set_parameters = in_set_parameters;
9193 in->stream.common.get_parameters = in_get_parameters;
9194 in->stream.common.add_audio_effect = in_add_audio_effect;
9195 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9196 in->stream.set_gain = in_set_gain;
9197 in->stream.read = in_read;
9198 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009199 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309200 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009201 in->stream.set_microphone_direction = in_set_microphone_direction;
9202 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009203 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009204
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009205 list_init(&in->device_list);
9206 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009207 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009208 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009209 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009210 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009211 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009212 in->bit_width = 16;
9213 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009214 in->direction = MIC_DIRECTION_UNSPECIFIED;
9215 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009216 list_init(&in->aec_list);
9217 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009218 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009219
Andy Hung94320602018-10-29 18:31:12 -07009220 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009221 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9222 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9223 /* Force channel config requested to mono if incall
9224 record is being requested for only uplink/downlink */
9225 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9226 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9227 ret = -EINVAL;
9228 goto err_open;
9229 }
9230 }
9231
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009232 if (is_usb_dev && may_use_hifi_record) {
9233 /* HiFi record selects an appropriate format, channel, rate combo
9234 depending on sink capabilities*/
9235 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9236 &config->format,
9237 &in->supported_formats[0],
9238 MAX_SUPPORTED_FORMATS,
9239 &config->channel_mask,
9240 &in->supported_channel_masks[0],
9241 MAX_SUPPORTED_CHANNEL_MASKS,
9242 &config->sample_rate,
9243 &in->supported_sample_rates[0],
9244 MAX_SUPPORTED_SAMPLE_RATES);
9245 if (ret != 0) {
9246 ret = -EINVAL;
9247 goto err_open;
9248 }
9249 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009250 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309251 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309252 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9253 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9254 in->config.format = PCM_FORMAT_S32_LE;
9255 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309256 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9257 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9258 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9259 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9260 bool ret_error = false;
9261 in->bit_width = 24;
9262 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9263 from HAL is 24_packed and 8_24
9264 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9265 24_packed return error indicating supported format is 24_packed
9266 *> In case of any other source requesting 24 bit or float return error
9267 indicating format supported is 16 bit only.
9268
9269 on error flinger will retry with supported format passed
9270 */
9271 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9272 (source != AUDIO_SOURCE_CAMCORDER)) {
9273 config->format = AUDIO_FORMAT_PCM_16_BIT;
9274 if (config->sample_rate > 48000)
9275 config->sample_rate = 48000;
9276 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009277 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9278 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309279 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9280 ret_error = true;
9281 }
9282
9283 if (ret_error) {
9284 ret = -EINVAL;
9285 goto err_open;
9286 }
9287 }
9288
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009289 in->channel_mask = config->channel_mask;
9290 in->format = config->format;
9291
9292 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309293
9294 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9295 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9296 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9297 else {
9298 ret = -EINVAL;
9299 goto err_open;
9300 }
9301 }
9302
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009303 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309304 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9305 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009306 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9307 is_low_latency = true;
9308#if LOW_LATENCY_CAPTURE_USE_CASE
9309 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9310#endif
9311 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009312 if (!in->realtime) {
9313 in->config = pcm_config_audio_capture;
9314 frame_size = audio_stream_in_frame_size(&in->stream);
9315 buffer_size = get_input_buffer_size(config->sample_rate,
9316 config->format,
9317 channel_count,
9318 is_low_latency);
9319 in->config.period_size = buffer_size / frame_size;
9320 in->config.rate = config->sample_rate;
9321 in->af_period_multiplier = 1;
9322 } else {
9323 // period size is left untouched for rt mode playback
9324 in->config = pcm_config_audio_capture_rt;
9325 in->af_period_multiplier = af_period_multiplier;
9326 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009327 }
9328
9329 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9330 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9331 in->realtime = 0;
9332 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9333 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009334 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009335 in->stream.start = in_start;
9336 in->stream.stop = in_stop;
9337 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9338 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009339 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009340 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009341 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9342 in->config = pcm_config_audio_capture;
9343 frame_size = audio_stream_in_frame_size(&in->stream);
9344 buffer_size = get_input_buffer_size(config->sample_rate,
9345 config->format,
9346 channel_count,
9347 false /*is_low_latency*/);
9348 in->config.period_size = buffer_size / frame_size;
9349 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009350 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009351 switch (config->format) {
9352 case AUDIO_FORMAT_PCM_32_BIT:
9353 in->bit_width = 32;
9354 break;
9355 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9356 case AUDIO_FORMAT_PCM_8_24_BIT:
9357 in->bit_width = 24;
9358 break;
9359 default:
9360 in->bit_width = 16;
9361 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009362 } else if (is_single_device_type_equal(&in->device_list,
9363 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9364 is_single_device_type_equal(&in->device_list,
9365 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009366 if (config->sample_rate == 0)
9367 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9368 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9369 config->sample_rate != 8000) {
9370 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9371 ret = -EINVAL;
9372 goto err_open;
9373 }
9374 if (config->format == AUDIO_FORMAT_DEFAULT)
9375 config->format = AUDIO_FORMAT_PCM_16_BIT;
9376 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9377 config->format = AUDIO_FORMAT_PCM_16_BIT;
9378 ret = -EINVAL;
9379 goto err_open;
9380 }
9381
9382 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009383 if (adev->ha_proxy_enable &&
9384 is_single_device_type_equal(&in->device_list,
9385 AUDIO_DEVICE_IN_TELEPHONY_RX))
9386 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009387 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009388 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009389 in->af_period_multiplier = 1;
9390 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9391 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9392 (config->sample_rate == 8000 ||
9393 config->sample_rate == 16000 ||
9394 config->sample_rate == 32000 ||
9395 config->sample_rate == 48000) &&
9396 channel_count == 1) {
9397 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9398 in->config = pcm_config_audio_capture;
9399 frame_size = audio_stream_in_frame_size(&in->stream);
9400 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9401 config->sample_rate,
9402 config->format,
9403 channel_count, false /*is_low_latency*/);
9404 in->config.period_size = buffer_size / frame_size;
9405 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9406 in->config.rate = config->sample_rate;
9407 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009408 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309409 int ret_val;
9410 pthread_mutex_lock(&adev->lock);
9411 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9412 in, config, &channel_mask_updated);
9413 pthread_mutex_unlock(&adev->lock);
9414
9415 if (!ret_val) {
9416 if (channel_mask_updated == true) {
9417 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9418 __func__, config->channel_mask);
9419 ret = -EINVAL;
9420 goto err_open;
9421 }
9422 ALOGD("%s: created multi-channel session succesfully",__func__);
9423 } else if (audio_extn_compr_cap_enabled() &&
9424 audio_extn_compr_cap_format_supported(config->format) &&
9425 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9426 audio_extn_compr_cap_init(in);
9427 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309428 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309429 if (ret)
9430 goto err_open;
9431 } else {
9432 in->config = pcm_config_audio_capture;
9433 in->config.rate = config->sample_rate;
9434 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309435 in->format = config->format;
9436 frame_size = audio_stream_in_frame_size(&in->stream);
9437 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009438 config->format,
9439 channel_count,
9440 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009441 /* prevent division-by-zero */
9442 if (frame_size == 0) {
9443 ALOGE("%s: Error frame_size==0", __func__);
9444 ret = -EINVAL;
9445 goto err_open;
9446 }
9447
Revathi Uddarajud2634032017-12-07 14:42:34 +05309448 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009449 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009450
Revathi Uddarajud2634032017-12-07 14:42:34 +05309451 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9452 /* optionally use VOIP usecase depending on config(s) */
9453 ret = adev_update_voice_comm_input_stream(in, config);
9454 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009455
Revathi Uddarajud2634032017-12-07 14:42:34 +05309456 if (ret) {
9457 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9458 goto err_open;
9459 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009460 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309461
9462 /* assign concurrent capture usecase if record has to caried out from
9463 * actual hardware input source */
9464 if (audio_extn_is_concurrent_capture_enabled() &&
9465 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309466 /* Acquire lock to avoid two concurrent use cases initialized to
9467 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009468
Samyak Jainc37062f2019-04-25 18:41:06 +05309469 if (in->usecase == USECASE_AUDIO_RECORD) {
9470 pthread_mutex_lock(&adev->lock);
9471 if (!(adev->pcm_record_uc_state)) {
9472 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9473 adev->pcm_record_uc_state = 1;
9474 pthread_mutex_unlock(&adev->lock);
9475 } else {
9476 pthread_mutex_unlock(&adev->lock);
9477 /* Assign compress record use case for second record */
9478 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9479 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9480 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9481 if (audio_extn_cin_applicable_stream(in)) {
9482 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309483 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309484 if (ret)
9485 goto err_open;
9486 }
9487 }
9488 }
kunleiz28c73e72019-03-27 17:24:04 +08009489 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009490 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309491 if (audio_extn_ssr_get_stream() != in)
9492 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009493
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009494 in->sample_rate = in->config.rate;
9495
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309496 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9497 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009498 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009499 in->sample_rate, in->bit_width,
9500 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309501 register_format(in->format, in->supported_formats);
9502 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9503 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309504
Aalique Grahame22e49102018-12-18 14:23:57 -08009505 in->error_log = error_log_create(
9506 ERROR_LOG_ENTRIES,
9507 1000000000 /* aggregate consecutive identical errors within one second */);
9508
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009509 /* This stream could be for sound trigger lab,
9510 get sound trigger pcm if present */
9511 audio_extn_sound_trigger_check_and_get_session(in);
9512
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309513 lock_input_stream(in);
9514 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9515 pthread_mutex_lock(&adev->lock);
9516 in->card_status = adev->card_status;
9517 pthread_mutex_unlock(&adev->lock);
9518 pthread_mutex_unlock(&in->lock);
9519
Aalique Grahame22e49102018-12-18 14:23:57 -08009520 stream_app_type_cfg_init(&in->app_type_cfg);
9521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009522 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009523
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009524 ret = io_streams_map_insert(adev, &in->stream.common,
9525 handle, AUDIO_PATCH_HANDLE_NONE);
9526 if (ret != 0)
9527 goto err_open;
9528
Derek Chenf939fb72018-11-13 13:34:41 -08009529 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9530 calloc(1, sizeof(streams_input_ctxt_t));
9531 if (in_ctxt == NULL) {
9532 ALOGE("%s fail to allocate input ctxt", __func__);
9533 ret = -ENOMEM;
9534 goto err_open;
9535 }
9536 in_ctxt->input = in;
9537
9538 pthread_mutex_lock(&adev->lock);
9539 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9540 pthread_mutex_unlock(&adev->lock);
9541
Eric Laurent994a6932013-07-17 11:51:42 -07009542 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009543 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009544
9545err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309546 if (in->usecase == USECASE_AUDIO_RECORD) {
9547 pthread_mutex_lock(&adev->lock);
9548 adev->pcm_record_uc_state = 0;
9549 pthread_mutex_unlock(&adev->lock);
9550 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009551 free(in);
9552 *stream_in = NULL;
9553 return ret;
9554}
9555
9556static void adev_close_input_stream(struct audio_hw_device *dev,
9557 struct audio_stream_in *stream)
9558{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009559 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009560 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009561 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309562
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309563 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009564
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009565 if (in == NULL) {
9566 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9567 return;
9568 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009569 io_streams_map_remove(adev, in->capture_handle);
9570
kunleiz70e57612018-12-28 17:50:23 +08009571 /* must deregister from sndmonitor first to prevent races
9572 * between the callback and close_stream
9573 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309574 audio_extn_snd_mon_unregister_listener(stream);
9575
kunleiz70e57612018-12-28 17:50:23 +08009576 /* Disable echo reference if there are no active input, hfp call
9577 * and sound trigger while closing input stream
9578 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009579 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009580 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009581 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9582 struct listnode out_devices;
9583 list_init(&out_devices);
9584 platform_set_echo_reference(adev, false, &out_devices);
9585 } else
kunleiz70e57612018-12-28 17:50:23 +08009586 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309587
Weiyin Jiang2995f662019-04-17 14:25:12 +08009588 error_log_destroy(in->error_log);
9589 in->error_log = NULL;
9590
Pallavid7c7a272018-01-16 11:22:55 +05309591
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009592 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309593 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009594 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309595 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009596 if (ret != 0)
9597 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9598 __func__, ret);
9599 } else
9600 in_standby(&stream->common);
9601
Revathi Uddarajud2634032017-12-07 14:42:34 +05309602 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309603 if (in->usecase == USECASE_AUDIO_RECORD) {
9604 adev->pcm_record_uc_state = 0;
9605 }
9606
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009607 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9608 adev->enable_voicerx = false;
9609 }
9610
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009611 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009612 audio_extn_ssr_deinit();
9613 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009614
Garmond Leunge2433c32017-09-28 21:51:22 -07009615 if (audio_extn_ffv_get_stream() == in) {
9616 audio_extn_ffv_stream_deinit();
9617 }
9618
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309619 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009620 audio_extn_compr_cap_format_supported(in->config.format))
9621 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309622
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309623 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309624 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009625
Mingming Yinfd7607b2016-01-22 12:48:44 -08009626 if (in->is_st_session) {
9627 ALOGV("%s: sound trigger pcm stop lab", __func__);
9628 audio_extn_sound_trigger_stop_lab(in);
9629 }
Derek Chenf939fb72018-11-13 13:34:41 -08009630 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9631 if (in_ctxt != NULL) {
9632 list_remove(&in_ctxt->list);
9633 free(in_ctxt);
9634 } else {
9635 ALOGW("%s, input stream already closed", __func__);
9636 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009637 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309638 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009639 return;
9640}
9641
Aalique Grahame22e49102018-12-18 14:23:57 -08009642/* verifies input and output devices and their capabilities.
9643 *
9644 * This verification is required when enabling extended bit-depth or
9645 * sampling rates, as not all qcom products support it.
9646 *
9647 * Suitable for calling only on initialization such as adev_open().
9648 * It fills the audio_device use_case_table[] array.
9649 *
9650 * Has a side-effect that it needs to configure audio routing / devices
9651 * in order to power up the devices and read the device parameters.
9652 * It does not acquire any hw device lock. Should restore the devices
9653 * back to "normal state" upon completion.
9654 */
9655static int adev_verify_devices(struct audio_device *adev)
9656{
9657 /* enumeration is a bit difficult because one really wants to pull
9658 * the use_case, device id, etc from the hidden pcm_device_table[].
9659 * In this case there are the following use cases and device ids.
9660 *
9661 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9662 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9663 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9664 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9665 * [USECASE_AUDIO_RECORD] = {0, 0},
9666 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9667 * [USECASE_VOICE_CALL] = {2, 2},
9668 *
9669 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9670 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9671 */
9672
9673 /* should be the usecases enabled in adev_open_input_stream() */
9674 static const int test_in_usecases[] = {
9675 USECASE_AUDIO_RECORD,
9676 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9677 };
9678 /* should be the usecases enabled in adev_open_output_stream()*/
9679 static const int test_out_usecases[] = {
9680 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9681 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9682 };
9683 static const usecase_type_t usecase_type_by_dir[] = {
9684 PCM_PLAYBACK,
9685 PCM_CAPTURE,
9686 };
9687 static const unsigned flags_by_dir[] = {
9688 PCM_OUT,
9689 PCM_IN,
9690 };
9691
9692 size_t i;
9693 unsigned dir;
9694 const unsigned card_id = adev->snd_card;
9695
9696 for (dir = 0; dir < 2; ++dir) {
9697 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9698 const unsigned flags_dir = flags_by_dir[dir];
9699 const size_t testsize =
9700 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9701 const int *testcases =
9702 dir ? test_in_usecases : test_out_usecases;
9703 const audio_devices_t audio_device =
9704 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9705
9706 for (i = 0; i < testsize; ++i) {
9707 const audio_usecase_t audio_usecase = testcases[i];
9708 int device_id;
9709 struct pcm_params **pparams;
9710 struct stream_out out;
9711 struct stream_in in;
9712 struct audio_usecase uc_info;
9713 int retval;
9714
9715 pparams = &adev->use_case_table[audio_usecase];
9716 pcm_params_free(*pparams); /* can accept null input */
9717 *pparams = NULL;
9718
9719 /* find the device ID for the use case (signed, for error) */
9720 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9721 if (device_id < 0)
9722 continue;
9723
9724 /* prepare structures for device probing */
9725 memset(&uc_info, 0, sizeof(uc_info));
9726 uc_info.id = audio_usecase;
9727 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009728 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009729 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009730 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009731 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009732 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009733 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9734 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009735 }
9736 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009737 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009738 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009739 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009740 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009741 uc_info.in_snd_device = SND_DEVICE_NONE;
9742 uc_info.out_snd_device = SND_DEVICE_NONE;
9743 list_add_tail(&adev->usecase_list, &uc_info.list);
9744
9745 /* select device - similar to start_(in/out)put_stream() */
9746 retval = select_devices(adev, audio_usecase);
9747 if (retval >= 0) {
9748 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9749#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009750 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009751 if (*pparams) {
9752 ALOGV("%s: (%s) card %d device %d", __func__,
9753 dir ? "input" : "output", card_id, device_id);
9754 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9755 } else {
9756 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9757 }
9758#endif
9759 }
9760
9761 /* deselect device - similar to stop_(in/out)put_stream() */
9762 /* 1. Get and set stream specific mixer controls */
9763 retval = disable_audio_route(adev, &uc_info);
9764 /* 2. Disable the rx device */
9765 retval = disable_snd_device(adev,
9766 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9767 list_remove(&uc_info.list);
9768 }
9769 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009770 return 0;
9771}
9772
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009773int update_patch(unsigned int num_sources,
9774 const struct audio_port_config *sources,
9775 unsigned int num_sinks,
9776 const struct audio_port_config *sinks,
9777 audio_patch_handle_t handle,
9778 struct audio_patch_info *p_info,
9779 patch_type_t patch_type, bool new_patch)
9780{
9781 ALOGD("%s: enter", __func__);
9782
9783 if (p_info == NULL) {
9784 ALOGE("%s: Invalid patch pointer", __func__);
9785 return -EINVAL;
9786 }
9787
9788 if (new_patch) {
9789 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9790 if (p_info->patch == NULL) {
9791 ALOGE("%s: Could not allocate patch", __func__);
9792 return -ENOMEM;
9793 }
9794 }
9795
9796 p_info->patch->id = handle;
9797 p_info->patch->num_sources = num_sources;
9798 p_info->patch->num_sinks = num_sinks;
9799
9800 for (int i = 0; i < num_sources; i++)
9801 p_info->patch->sources[i] = sources[i];
9802 for (int i = 0; i < num_sinks; i++)
9803 p_info->patch->sinks[i] = sinks[i];
9804
9805 p_info->patch_type = patch_type;
9806 return 0;
9807}
9808
9809audio_patch_handle_t generate_patch_handle()
9810{
9811 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9812 if (++patch_handle < 0)
9813 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9814 return patch_handle;
9815}
9816
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309817int adev_create_audio_patch(struct audio_hw_device *dev,
9818 unsigned int num_sources,
9819 const struct audio_port_config *sources,
9820 unsigned int num_sinks,
9821 const struct audio_port_config *sinks,
9822 audio_patch_handle_t *handle)
9823{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009824 int ret = 0;
9825 struct audio_device *adev = (struct audio_device *)dev;
9826 struct audio_patch_info *p_info = NULL;
9827 patch_type_t patch_type = PATCH_NONE;
9828 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9829 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9830 struct audio_stream_info *s_info = NULL;
9831 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009832 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009833 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9834 bool new_patch = false;
9835 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309836
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009837 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9838 num_sources, num_sinks, *handle);
9839
9840 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9841 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9842 ALOGE("%s: Invalid patch arguments", __func__);
9843 ret = -EINVAL;
9844 goto done;
9845 }
9846
9847 if (num_sources > 1) {
9848 ALOGE("%s: Multiple sources are not supported", __func__);
9849 ret = -EINVAL;
9850 goto done;
9851 }
9852
9853 if (sources == NULL || sinks == NULL) {
9854 ALOGE("%s: Invalid sources or sinks port config", __func__);
9855 ret = -EINVAL;
9856 goto done;
9857 }
9858
9859 ALOGV("%s: source role %d, source type %d", __func__,
9860 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009861 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009862
9863 // Populate source/sink information and fetch stream info
9864 switch (sources[0].type) {
9865 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9866 device_type = sources[0].ext.device.type;
9867 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009868 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009869 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9870 patch_type = PATCH_CAPTURE;
9871 io_handle = sinks[0].ext.mix.handle;
9872 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009873 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009874 __func__, device_type, io_handle);
9875 } else {
9876 // Device to device patch is not implemented.
9877 // This space will need changes if audio HAL
9878 // handles device to device patches in the future.
9879 patch_type = PATCH_DEVICE_LOOPBACK;
9880 }
9881 break;
9882 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9883 io_handle = sources[0].ext.mix.handle;
9884 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009885 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009886 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009887 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009888 }
9889 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009890 ALOGD("%s: Playback patch from mix handle %d to device %x",
9891 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009892 break;
9893 case AUDIO_PORT_TYPE_SESSION:
9894 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009895 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9896 ret = -EINVAL;
9897 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009898 }
9899
9900 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009901
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009902 // Generate patch info and update patch
9903 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009904 *handle = generate_patch_handle();
9905 p_info = (struct audio_patch_info *)
9906 calloc(1, sizeof(struct audio_patch_info));
9907 if (p_info == NULL) {
9908 ALOGE("%s: Failed to allocate memory", __func__);
9909 pthread_mutex_unlock(&adev->lock);
9910 ret = -ENOMEM;
9911 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009912 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009913 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009914 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009915 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009916 if (p_info == NULL) {
9917 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9918 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009919 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009920 ret = -EINVAL;
9921 goto done;
9922 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009923 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009924 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009925 *handle, p_info, patch_type, new_patch);
9926
9927 // Fetch stream info of associated mix for playback or capture patches
9928 if (p_info->patch_type == PATCH_PLAYBACK ||
9929 p_info->patch_type == PATCH_CAPTURE) {
9930 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9931 if (s_info == NULL) {
9932 ALOGE("%s: Failed to obtain stream info", __func__);
9933 if (new_patch)
9934 free(p_info);
9935 pthread_mutex_unlock(&adev->lock);
9936 ret = -EINVAL;
9937 goto done;
9938 }
9939 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9940 s_info->patch_handle = *handle;
9941 stream = s_info->stream;
9942 }
9943 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009944
9945 // Update routing for stream
9946 if (stream != NULL) {
9947 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009948 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009949 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009950 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009951 if (ret < 0) {
9952 pthread_mutex_lock(&adev->lock);
9953 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9954 if (new_patch)
9955 free(p_info);
9956 pthread_mutex_unlock(&adev->lock);
9957 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9958 goto done;
9959 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009960 }
9961
9962 // Add new patch to patch map
9963 if (!ret && new_patch) {
9964 pthread_mutex_lock(&adev->lock);
9965 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009966 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009967 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009968 }
9969
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009970done:
9971 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009972 num_sources,
9973 sources,
9974 num_sinks,
9975 sinks,
9976 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009977 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009978 num_sources,
9979 sources,
9980 num_sinks,
9981 sinks,
9982 handle);
9983 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309984}
9985
9986int adev_release_audio_patch(struct audio_hw_device *dev,
9987 audio_patch_handle_t handle)
9988{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009989 struct audio_device *adev = (struct audio_device *) dev;
9990 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009991 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009992 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -08009993
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009994 if (handle == AUDIO_PATCH_HANDLE_NONE) {
9995 ALOGE("%s: Invalid patch handle %d", __func__, handle);
9996 ret = -EINVAL;
9997 goto done;
9998 }
9999
10000 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010001 pthread_mutex_lock(&adev->lock);
10002 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010003 if (p_info == NULL) {
10004 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010005 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010006 ret = -EINVAL;
10007 goto done;
10008 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010009 struct audio_patch *patch = p_info->patch;
10010 if (patch == NULL) {
10011 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010012 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010013 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010014 goto done;
10015 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010016 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10017 switch (patch->sources[0].type) {
10018 case AUDIO_PORT_TYPE_MIX:
10019 io_handle = patch->sources[0].ext.mix.handle;
10020 break;
10021 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010022 if (p_info->patch_type == PATCH_CAPTURE)
10023 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010024 break;
10025 case AUDIO_PORT_TYPE_SESSION:
10026 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010027 pthread_mutex_unlock(&adev->lock);
10028 ret = -EINVAL;
10029 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010030 }
10031
10032 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010033 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010034 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010035 if (patch_type == PATCH_PLAYBACK ||
10036 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010037 struct audio_stream_info *s_info =
10038 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10039 if (s_info == NULL) {
10040 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10041 pthread_mutex_unlock(&adev->lock);
10042 goto done;
10043 }
10044 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10045 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010046 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010047 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010048
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010049 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010050 struct listnode devices;
10051 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010052 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010053 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010054 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010055 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010056 }
10057
10058 if (ret < 0)
10059 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10060
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010061done:
10062 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10063 audio_extn_auto_hal_release_audio_patch(dev, handle);
10064
10065 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010066 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010067}
10068
10069int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10070{
Derek Chenf13dd492018-11-13 14:53:51 -080010071 int ret = 0;
10072
10073 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10074 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10075 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010076}
10077
10078int adev_set_audio_port_config(struct audio_hw_device *dev,
10079 const struct audio_port_config *config)
10080{
Derek Chenf13dd492018-11-13 14:53:51 -080010081 int ret = 0;
10082
10083 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10084 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10085 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010086}
10087
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010088static int adev_dump(const audio_hw_device_t *device __unused,
10089 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010090{
10091 return 0;
10092}
10093
10094static int adev_close(hw_device_t *device)
10095{
Aalique Grahame22e49102018-12-18 14:23:57 -080010096 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010097 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010098
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010099 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010100 return 0;
10101
10102 pthread_mutex_lock(&adev_init_lock);
10103
10104 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010105 if (audio_extn_spkr_prot_is_enabled())
10106 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010107 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010108 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010109 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010110 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010111 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010112 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010113 audio_extn_utils_release_streams_cfg_lists(
10114 &adev->streams_output_cfg_list,
10115 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010116 if (audio_extn_qap_is_enabled())
10117 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010118 if (audio_extn_qaf_is_enabled())
10119 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010120 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010121 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010122 free(adev->snd_dev_ref_cnt);
10123 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010124 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10125 pcm_params_free(adev->use_case_table[i]);
10126 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010127 if (adev->adm_deinit)
10128 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010129 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010130 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010131 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010132 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010133 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010134 if (adev->device_cfg_params) {
10135 free(adev->device_cfg_params);
10136 adev->device_cfg_params = NULL;
10137 }
Derek Chend2530072014-11-24 12:39:14 -080010138 if(adev->ext_hw_plugin)
10139 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010140 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010141 free_map(adev->patch_map);
10142 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010143 free(device);
10144 adev = NULL;
10145 }
10146 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010147 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010148 return 0;
10149}
10150
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010151/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10152 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10153 * just that it _might_ work.
10154 */
10155static int period_size_is_plausible_for_low_latency(int period_size)
10156{
10157 switch (period_size) {
10158 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010159 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010160 case 240:
10161 case 320:
10162 case 480:
10163 return 1;
10164 default:
10165 return 0;
10166 }
10167}
10168
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010169static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10170{
10171 bool is_snd_card_status = false;
10172 bool is_ext_device_status = false;
10173 char value[32];
10174 int card = -1;
10175 card_status_t status;
10176
10177 if (cookie != adev || !parms)
10178 return;
10179
10180 if (!parse_snd_card_status(parms, &card, &status)) {
10181 is_snd_card_status = true;
10182 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10183 is_ext_device_status = true;
10184 } else {
10185 // not a valid event
10186 return;
10187 }
10188
10189 pthread_mutex_lock(&adev->lock);
10190 if (card == adev->snd_card || is_ext_device_status) {
10191 if (is_snd_card_status && adev->card_status != status) {
10192 adev->card_status = status;
10193 platform_snd_card_update(adev->platform, status);
10194 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010195 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010196 if (status == CARD_STATUS_OFFLINE)
10197 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010198 } else if (is_ext_device_status) {
10199 platform_set_parameters(adev->platform, parms);
10200 }
10201 }
10202 pthread_mutex_unlock(&adev->lock);
10203 return;
10204}
10205
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010206/* out and adev lock held */
10207static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10208{
10209 struct audio_usecase *uc_info;
10210 float left_p;
10211 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010212 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010213
10214 uc_info = get_usecase_from_list(adev, out->usecase);
10215 if (uc_info == NULL) {
10216 ALOGE("%s: Could not find the usecase (%d) in the list",
10217 __func__, out->usecase);
10218 return -EINVAL;
10219 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010220 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010221
10222 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10223 out->usecase, use_case_table[out->usecase]);
10224
10225 if (restore) {
10226 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010227 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010228 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010229 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10230 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010231 pthread_mutex_lock(&out->compr_mute_lock);
10232 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010233 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010234 out->a2dp_compress_mute = false;
10235 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10236 }
10237 pthread_mutex_unlock(&out->compr_mute_lock);
10238 }
10239 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010240 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10241 // mute compress stream if suspended
10242 pthread_mutex_lock(&out->compr_mute_lock);
10243 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010244 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010245 assign_devices(&devices, &out->device_list);
10246 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010247 left_p = out->volume_l;
10248 right_p = out->volume_r;
10249 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10250 compress_pause(out->compr);
10251 out_set_compr_volume(&out->stream, (float)0, (float)0);
10252 out->a2dp_compress_mute = true;
10253 select_devices(adev, out->usecase);
10254 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10255 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010256 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010257 out->volume_l = left_p;
10258 out->volume_r = right_p;
10259 }
Zhou Songc576a452019-09-09 14:17:40 +080010260 pthread_mutex_unlock(&out->compr_mute_lock);
10261 } else {
10262 // tear down a2dp path for non offloaded streams
10263 if (audio_extn_a2dp_source_is_suspended())
10264 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010265 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010266 }
10267 ALOGV("%s: exit", __func__);
10268 return 0;
10269}
10270
10271int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10272{
10273 int ret = 0;
10274
10275 lock_output_stream(out);
10276 pthread_mutex_lock(&adev->lock);
10277
10278 ret = check_a2dp_restore_l(adev, out, restore);
10279
10280 pthread_mutex_unlock(&adev->lock);
10281 pthread_mutex_unlock(&out->lock);
10282 return ret;
10283}
10284
Haynes Mathew George01156f92018-04-13 15:29:54 -070010285void adev_on_battery_status_changed(bool charging)
10286{
10287 pthread_mutex_lock(&adev->lock);
10288 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10289 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010290 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010291 pthread_mutex_unlock(&adev->lock);
10292}
10293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010294static int adev_open(const hw_module_t *module, const char *name,
10295 hw_device_t **device)
10296{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010297 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010298 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010299 char mixer_ctl_name[128] = {0};
10300 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010301
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010302 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010303 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10304
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010305 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010306 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010307 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010308 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010309 ALOGD("%s: returning existing instance of adev", __func__);
10310 ALOGD("%s: exit", __func__);
10311 pthread_mutex_unlock(&adev_init_lock);
10312 return 0;
10313 }
10314
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010315 adev = calloc(1, sizeof(struct audio_device));
10316
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010317 if (!adev) {
10318 pthread_mutex_unlock(&adev_init_lock);
10319 return -ENOMEM;
10320 }
10321
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010322 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10323
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010324 // register audio ext hidl at the earliest
10325 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010326#ifdef DYNAMIC_LOG_ENABLED
10327 register_for_dynamic_logging("hal");
10328#endif
10329
Derek Chenf939fb72018-11-13 13:34:41 -080010330 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010331 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010332 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10333 maj_version = atoi(value);
10334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010335 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010336 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010337 adev->device.common.module = (struct hw_module_t *)module;
10338 adev->device.common.close = adev_close;
10339
10340 adev->device.init_check = adev_init_check;
10341 adev->device.set_voice_volume = adev_set_voice_volume;
10342 adev->device.set_master_volume = adev_set_master_volume;
10343 adev->device.get_master_volume = adev_get_master_volume;
10344 adev->device.set_master_mute = adev_set_master_mute;
10345 adev->device.get_master_mute = adev_get_master_mute;
10346 adev->device.set_mode = adev_set_mode;
10347 adev->device.set_mic_mute = adev_set_mic_mute;
10348 adev->device.get_mic_mute = adev_get_mic_mute;
10349 adev->device.set_parameters = adev_set_parameters;
10350 adev->device.get_parameters = adev_get_parameters;
10351 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10352 adev->device.open_output_stream = adev_open_output_stream;
10353 adev->device.close_output_stream = adev_close_output_stream;
10354 adev->device.open_input_stream = adev_open_input_stream;
10355 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010356 adev->device.create_audio_patch = adev_create_audio_patch;
10357 adev->device.release_audio_patch = adev_release_audio_patch;
10358 adev->device.get_audio_port = adev_get_audio_port;
10359 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010360 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010361 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010362
10363 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010364 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010365 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010366 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010367 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010368 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010369 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010370 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010371 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010372 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010373 /* Init audio and voice feature */
10374 audio_extn_feature_init();
10375 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010376 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010377 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010378 list_init(&adev->active_inputs_list);
10379 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010380 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010381 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10382 audio_extn_utils_hash_eq);
10383 if (!adev->io_streams_map) {
10384 ALOGE("%s: Could not create io streams map", __func__);
10385 ret = -ENOMEM;
10386 goto adev_open_err;
10387 }
10388 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10389 audio_extn_utils_hash_eq);
10390 if (!adev->patch_map) {
10391 ALOGE("%s: Could not create audio patch map", __func__);
10392 ret = -ENOMEM;
10393 goto adev_open_err;
10394 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010395 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010396 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010397 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010398 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010399 adev->perf_lock_opts[0] = 0x101;
10400 adev->perf_lock_opts[1] = 0x20E;
10401 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010402 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010403 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010404 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010405 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010406
Zhou Song68ebc352019-12-05 17:11:15 +080010407 audio_extn_perf_lock_init();
10408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010409 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010410 adev->platform = platform_init(adev);
10411 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010412 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010413 ret = -EINVAL;
10414 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010415 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010416
Aalique Grahame22e49102018-12-18 14:23:57 -080010417 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010418 if (audio_extn_qap_is_enabled()) {
10419 ret = audio_extn_qap_init(adev);
10420 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010421 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010422 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010423 }
10424 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10425 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10426 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010427
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010428 if (audio_extn_qaf_is_enabled()) {
10429 ret = audio_extn_qaf_init(adev);
10430 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010431 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010432 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010433 }
10434
10435 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10436 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10437 }
10438
Derek Chenae7b0342019-02-08 15:17:04 -080010439 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010440 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10441
Eric Laurentc4aef752013-09-12 17:45:53 -070010442 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10443 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10444 if (adev->visualizer_lib == NULL) {
10445 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10446 } else {
10447 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10448 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010449 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010450 "visualizer_hal_start_output");
10451 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010452 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010453 "visualizer_hal_stop_output");
10454 }
10455 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010456 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010457 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010458 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010459 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010460 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010461 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010462
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010463 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10464 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10465 if (adev->offload_effects_lib == NULL) {
10466 ALOGE("%s: DLOPEN failed for %s", __func__,
10467 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10468 } else {
10469 ALOGV("%s: DLOPEN successful for %s", __func__,
10470 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10471 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010472 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010473 "offload_effects_bundle_hal_start_output");
10474 adev->offload_effects_stop_output =
10475 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10476 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010477 adev->offload_effects_set_hpx_state =
10478 (int (*)(bool))dlsym(adev->offload_effects_lib,
10479 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010480 adev->offload_effects_get_parameters =
10481 (void (*)(struct str_parms *, struct str_parms *))
10482 dlsym(adev->offload_effects_lib,
10483 "offload_effects_bundle_get_parameters");
10484 adev->offload_effects_set_parameters =
10485 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10486 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010487 }
10488 }
10489
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010490 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10491 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10492 if (adev->adm_lib == NULL) {
10493 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10494 } else {
10495 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10496 adev->adm_init = (adm_init_t)
10497 dlsym(adev->adm_lib, "adm_init");
10498 adev->adm_deinit = (adm_deinit_t)
10499 dlsym(adev->adm_lib, "adm_deinit");
10500 adev->adm_register_input_stream = (adm_register_input_stream_t)
10501 dlsym(adev->adm_lib, "adm_register_input_stream");
10502 adev->adm_register_output_stream = (adm_register_output_stream_t)
10503 dlsym(adev->adm_lib, "adm_register_output_stream");
10504 adev->adm_deregister_stream = (adm_deregister_stream_t)
10505 dlsym(adev->adm_lib, "adm_deregister_stream");
10506 adev->adm_request_focus = (adm_request_focus_t)
10507 dlsym(adev->adm_lib, "adm_request_focus");
10508 adev->adm_abandon_focus = (adm_abandon_focus_t)
10509 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010510 adev->adm_set_config = (adm_set_config_t)
10511 dlsym(adev->adm_lib, "adm_set_config");
10512 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10513 dlsym(adev->adm_lib, "adm_request_focus_v2");
10514 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10515 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10516 adev->adm_on_routing_change = (adm_on_routing_change_t)
10517 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010518 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10519 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010520 }
10521 }
10522
Aalique Grahame22e49102018-12-18 14:23:57 -080010523 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010524 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010525 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010526 //initialize this to false for now,
10527 //this will be set to true through set param
10528 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010529
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010530 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010531 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010532
10533 if (k_enable_extended_precision)
10534 adev_verify_devices(adev);
10535
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010536 adev->dsp_bit_width_enforce_mode =
10537 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010538
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010539 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10540 &adev->streams_output_cfg_list,
10541 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010542
Kiran Kandi910e1862013-10-29 13:29:42 -070010543 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010544
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010545 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010546 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010547 trial = atoi(value);
10548 if (period_size_is_plausible_for_low_latency(trial)) {
10549 pcm_config_low_latency.period_size = trial;
10550 pcm_config_low_latency.start_threshold = trial / 4;
10551 pcm_config_low_latency.avail_min = trial / 4;
10552 configured_low_latency_capture_period_size = trial;
10553 }
10554 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010555 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10556 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010557 trial = atoi(value);
10558 if (period_size_is_plausible_for_low_latency(trial)) {
10559 configured_low_latency_capture_period_size = trial;
10560 }
10561 }
10562
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010563 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10564
Eric Laurent4b084132018-10-19 17:33:43 -070010565 adev->camera_orientation = CAMERA_DEFAULT;
10566
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010567 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010568 af_period_multiplier = atoi(value);
10569 if (af_period_multiplier < 0)
10570 af_period_multiplier = 2;
10571 else if (af_period_multiplier > 4)
10572 af_period_multiplier = 4;
10573
10574 ALOGV("new period_multiplier = %d", af_period_multiplier);
10575 }
10576
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010577 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010578
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010579 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010580 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010581 pthread_mutex_unlock(&adev_init_lock);
10582
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010583 if (adev->adm_init)
10584 adev->adm_data = adev->adm_init();
10585
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010586 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010587 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010588
10589 audio_extn_snd_mon_init();
10590 pthread_mutex_lock(&adev->lock);
10591 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10592 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010593 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10594 /*
10595 * if the battery state callback happens before charging can be queried,
10596 * it will be guarded with the adev->lock held in the cb function and so
10597 * the callback value will reflect the latest state
10598 */
10599 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010600 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010601 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010602 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010603 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010604 /* Allocate memory for Device config params */
10605 adev->device_cfg_params = (struct audio_device_config_param*)
10606 calloc(platform_get_max_codec_backend(),
10607 sizeof(struct audio_device_config_param));
10608 if (adev->device_cfg_params == NULL)
10609 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010610
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010611 /*
10612 * Check if new PSPD matrix mixer control is supported. If not
10613 * supported, then set flag so that old mixer ctrl is sent while
10614 * sending pspd coefficients on older kernel version. Query mixer
10615 * control for default pcm id and channel value one.
10616 */
10617 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10618 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10619
10620 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10621 if (!ctl) {
10622 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10623 __func__, mixer_ctl_name);
10624 adev->use_old_pspd_mix_ctrl = true;
10625 }
10626
Eric Laurent994a6932013-07-17 11:51:42 -070010627 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010628 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010629
10630adev_open_err:
10631 free_map(adev->patch_map);
10632 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010633 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010634 pthread_mutex_destroy(&adev->lock);
10635 free(adev);
10636 adev = NULL;
10637 *device = NULL;
10638 pthread_mutex_unlock(&adev_init_lock);
10639 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010640}
10641
10642static struct hw_module_methods_t hal_module_methods = {
10643 .open = adev_open,
10644};
10645
10646struct audio_module HAL_MODULE_INFO_SYM = {
10647 .common = {
10648 .tag = HARDWARE_MODULE_TAG,
10649 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10650 .hal_api_version = HARDWARE_HAL_API_VERSION,
10651 .id = AUDIO_HARDWARE_MODULE_ID,
10652 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010653 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010654 .methods = &hal_module_methods,
10655 },
10656};