blob: 87d1ff6f6f53ea11e3401c8287c3209c105d308a [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080081#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080082
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053083#ifdef DYNAMIC_LOG_ENABLED
84#include <log_xml_parser.h>
85#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
86#include <log_utils.h>
87#endif
88
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053090/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
91#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070093#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070094#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053095#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053096#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070097#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070098#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070099
Aalique Grahame22e49102018-12-18 14:23:57 -0800100#define RECORD_GAIN_MIN 0.0f
101#define RECORD_GAIN_MAX 1.0f
102#define RECORD_VOLUME_CTL_MAX 0x2000
103
104/* treat as unsigned Q1.13 */
105#define APP_TYPE_GAIN_DEFAULT 0x2000
106
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700107#define PROXY_OPEN_RETRY_COUNT 100
108#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800109
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800110#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
111 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
112 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
113#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
114 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800115
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700116#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700117#define DEFAULT_VOIP_BUF_DURATION_MS 20
118#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
119#define DEFAULT_VOIP_SAMP_RATE 48000
120
121#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
122
123struct pcm_config default_pcm_config_voip_copp = {
124 .channels = 1,
125 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
126 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
127 .period_count = 2,
128 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800129 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
130 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700131};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700132
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700133#define MIN_CHANNEL_COUNT 1
134#define DEFAULT_CHANNEL_COUNT 2
135#define MAX_HIFI_CHANNEL_COUNT 8
136
Aalique Grahame22e49102018-12-18 14:23:57 -0800137#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
138#define MAX_CHANNEL_COUNT 1
139#else
140#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
141#define XSTR(x) STR(x)
142#define STR(x) #x
143#endif
144
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700145static unsigned int configured_low_latency_capture_period_size =
146 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
147
Haynes Mathew George16081042017-05-31 17:16:49 -0700148#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
149#define MMAP_PERIOD_COUNT_MIN 32
150#define MMAP_PERIOD_COUNT_MAX 512
151#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
152
Aalique Grahame22e49102018-12-18 14:23:57 -0800153/* This constant enables extended precision handling.
154 * TODO The flag is off until more testing is done.
155 */
156static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700157extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800158
Eric Laurentb23d5282013-05-14 15:27:20 -0700159struct pcm_config pcm_config_deep_buffer = {
160 .channels = 2,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
163 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
166 .stop_threshold = INT_MAX,
167 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
168};
169
170struct pcm_config pcm_config_low_latency = {
171 .channels = 2,
172 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
173 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
174 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
175 .format = PCM_FORMAT_S16_LE,
176 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
177 .stop_threshold = INT_MAX,
178 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
179};
180
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800181struct pcm_config pcm_config_haptics_audio = {
182 .channels = 1,
183 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
184 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
185 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
187 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
188 .stop_threshold = INT_MAX,
189 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
190};
191
192struct pcm_config pcm_config_haptics = {
193 .channels = 1,
194 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
195 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
196 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
197 .format = PCM_FORMAT_S16_LE,
198 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
199 .stop_threshold = INT_MAX,
200 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
201};
202
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700203static int af_period_multiplier = 4;
204struct pcm_config pcm_config_rt = {
205 .channels = 2,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = ULL_PERIOD_SIZE, //1 ms
208 .period_count = 512, //=> buffer size is 512ms
209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = ULL_PERIOD_SIZE, //1 ms
215};
216
Eric Laurentb23d5282013-05-14 15:27:20 -0700217struct pcm_config pcm_config_hdmi_multi = {
218 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
219 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
220 .period_size = HDMI_MULTI_PERIOD_SIZE,
221 .period_count = HDMI_MULTI_PERIOD_COUNT,
222 .format = PCM_FORMAT_S16_LE,
223 .start_threshold = 0,
224 .stop_threshold = INT_MAX,
225 .avail_min = 0,
226};
227
Haynes Mathew George16081042017-05-31 17:16:49 -0700228struct pcm_config pcm_config_mmap_playback = {
229 .channels = 2,
230 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
231 .period_size = MMAP_PERIOD_SIZE,
232 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
233 .format = PCM_FORMAT_S16_LE,
234 .start_threshold = MMAP_PERIOD_SIZE*8,
235 .stop_threshold = INT32_MAX,
236 .silence_threshold = 0,
237 .silence_size = 0,
238 .avail_min = MMAP_PERIOD_SIZE, //1 ms
239};
240
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700241struct pcm_config pcm_config_hifi = {
242 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
243 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
244 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
245 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
246 .format = PCM_FORMAT_S24_3LE,
247 .start_threshold = 0,
248 .stop_threshold = INT_MAX,
249 .avail_min = 0,
250};
251
Eric Laurentb23d5282013-05-14 15:27:20 -0700252struct pcm_config pcm_config_audio_capture = {
253 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700254 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
255 .format = PCM_FORMAT_S16_LE,
256};
257
Haynes Mathew George16081042017-05-31 17:16:49 -0700258struct pcm_config pcm_config_mmap_capture = {
259 .channels = 2,
260 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
261 .period_size = MMAP_PERIOD_SIZE,
262 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
263 .format = PCM_FORMAT_S16_LE,
264 .start_threshold = 0,
265 .stop_threshold = INT_MAX,
266 .silence_threshold = 0,
267 .silence_size = 0,
268 .avail_min = MMAP_PERIOD_SIZE, //1 ms
269};
270
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700271#define AFE_PROXY_CHANNEL_COUNT 2
272#define AFE_PROXY_SAMPLING_RATE 48000
273
274#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
275#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
276
277struct pcm_config pcm_config_afe_proxy_playback = {
278 .channels = AFE_PROXY_CHANNEL_COUNT,
279 .rate = AFE_PROXY_SAMPLING_RATE,
280 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
281 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
282 .format = PCM_FORMAT_S16_LE,
283 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
284 .stop_threshold = INT_MAX,
285 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286};
287
288#define AFE_PROXY_RECORD_PERIOD_SIZE 768
289#define AFE_PROXY_RECORD_PERIOD_COUNT 4
290
Aalique Grahame22e49102018-12-18 14:23:57 -0800291struct pcm_config pcm_config_audio_capture_rt = {
292 .channels = 2,
293 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
294 .period_size = ULL_PERIOD_SIZE,
295 .period_count = 512,
296 .format = PCM_FORMAT_S16_LE,
297 .start_threshold = 0,
298 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
299 .silence_threshold = 0,
300 .silence_size = 0,
301 .avail_min = ULL_PERIOD_SIZE, //1 ms
302};
303
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700304struct pcm_config pcm_config_afe_proxy_record = {
305 .channels = AFE_PROXY_CHANNEL_COUNT,
306 .rate = AFE_PROXY_SAMPLING_RATE,
307 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
308 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
309 .format = PCM_FORMAT_S16_LE,
310 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
311 .stop_threshold = INT_MAX,
312 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
313};
314
Ashish Jainf1eaa582016-05-23 20:54:24 +0530315#define AUDIO_MAX_PCM_FORMATS 7
316
317const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
318 [AUDIO_FORMAT_DEFAULT] = 0,
319 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
320 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
321 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
322 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
323 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
324 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
325};
326
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800327const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700328 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
329 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800330 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800331 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700332 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
333 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700334 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700335 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700336 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
341 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700344 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
345 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700346 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800347 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700348
Eric Laurentb23d5282013-05-14 15:27:20 -0700349 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700350 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530351 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
352 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
353 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530354 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
355 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700356 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700357 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700358 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700359 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700360
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800361 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800362 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400363 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
364 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700365
Derek Chenf7092792017-05-23 12:23:53 -0400366 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700367 [USECASE_VOICE2_CALL] = "voice2-call",
368 [USECASE_VOLTE_CALL] = "volte-call",
369 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800370 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800371 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
372 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800373 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700374 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
375 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
376 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800377 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
378 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
379 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
380
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700381 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
382 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700383 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
384 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700385
386 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
387 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800388 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530389 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700390
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530391 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530392 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
393 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700394
395 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
396 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530397 /* For Interactive Audio Streams */
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
401 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
402 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
403 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700406
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800407 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
408
Derek Chenf6318be2017-06-12 17:16:24 -0400409 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
410
411 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
412 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
413 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
414 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800415 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700416 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530417 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700418};
419
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700420static const audio_usecase_t offload_usecases[] = {
421 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700422 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
426 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
427 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
428 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700430};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800431
Varun Balaraje49253e2017-07-06 19:48:56 +0530432static const audio_usecase_t interactive_usecases[] = {
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
437 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
438 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
441};
442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443#define STRING_TO_ENUM(string) { #string, string }
444
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800445struct string_to_enum {
446 const char *name;
447 uint32_t value;
448};
449
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700450static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700455 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800456 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700459 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
460 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
461 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
466 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
467 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800470};
471
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700472static const struct string_to_enum formats_name_to_enum_table[] = {
473 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
474 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
475 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700476 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
477 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
478 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700479 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800480 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
481 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700482 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800483};
484
485//list of all supported sample rates by HDMI specification.
486static const int out_hdmi_sample_rates[] = {
487 32000, 44100, 48000, 88200, 96000, 176400, 192000,
488};
489
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700490static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800491 STRING_TO_ENUM(32000),
492 STRING_TO_ENUM(44100),
493 STRING_TO_ENUM(48000),
494 STRING_TO_ENUM(88200),
495 STRING_TO_ENUM(96000),
496 STRING_TO_ENUM(176400),
497 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800498 STRING_TO_ENUM(352800),
499 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700500};
501
Carter Hsu2e429db2019-05-14 18:50:52 +0800502struct in_effect_list {
503 struct listnode list;
504 effect_handle_t handle;
505};
506
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700507static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700508static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700509static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700510//cache last MBDRC cal step level
511static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700512
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530513static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
514static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700515static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800516static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530517static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530518
Derek Chen6f293672019-04-01 01:40:24 -0700519static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
520static void in_snd_mon_cb(void * stream, struct str_parms * parms);
521static void out_snd_mon_cb(void * stream, struct str_parms * parms);
522
Zhou Song331c8e52019-08-26 14:16:12 +0800523static int configure_btsco_sample_rate(snd_device_t snd_device);
524
Vatsal Buchac09ae062018-11-14 13:25:08 +0530525#ifdef AUDIO_FEATURE_ENABLED_GCOV
526extern void __gcov_flush();
527static void enable_gcov()
528{
529 __gcov_flush();
530}
531#else
532static void enable_gcov()
533{
534}
535#endif
536
justinweng20fb6d82019-02-21 18:49:00 -0700537static int in_set_microphone_direction(const struct audio_stream_in *stream,
538 audio_microphone_direction_t dir);
539static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
540
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700541static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
542 int flags __unused)
543{
544 int dir = 0;
545 switch (uc_id) {
546 case USECASE_AUDIO_RECORD_LOW_LATENCY:
547 dir = 1;
548 case USECASE_AUDIO_PLAYBACK_ULL:
549 break;
550 default:
551 return false;
552 }
553
554 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
555 PCM_PLAYBACK : PCM_CAPTURE);
556 if (adev->adm_is_noirq_avail)
557 return adev->adm_is_noirq_avail(adev->adm_data,
558 adev->snd_card, dev_id, dir);
559 return false;
560}
561
562static void register_out_stream(struct stream_out *out)
563{
564 struct audio_device *adev = out->dev;
565 if (is_offload_usecase(out->usecase) ||
566 !adev->adm_register_output_stream)
567 return;
568
569 // register stream first for backward compatibility
570 adev->adm_register_output_stream(adev->adm_data,
571 out->handle,
572 out->flags);
573
574 if (!adev->adm_set_config)
575 return;
576
577 if (out->realtime)
578 adev->adm_set_config(adev->adm_data,
579 out->handle,
580 out->pcm, &out->config);
581}
582
583static void register_in_stream(struct stream_in *in)
584{
585 struct audio_device *adev = in->dev;
586 if (!adev->adm_register_input_stream)
587 return;
588
589 adev->adm_register_input_stream(adev->adm_data,
590 in->capture_handle,
591 in->flags);
592
593 if (!adev->adm_set_config)
594 return;
595
596 if (in->realtime)
597 adev->adm_set_config(adev->adm_data,
598 in->capture_handle,
599 in->pcm,
600 &in->config);
601}
602
603static void request_out_focus(struct stream_out *out, long ns)
604{
605 struct audio_device *adev = out->dev;
606
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700607 if (adev->adm_request_focus_v2)
608 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
609 else if (adev->adm_request_focus)
610 adev->adm_request_focus(adev->adm_data, out->handle);
611}
612
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700613static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700614{
615 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700616 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700617
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700618 if (adev->adm_request_focus_v2_1)
619 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
620 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
622 else if (adev->adm_request_focus)
623 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700624
625 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700626}
627
628static void release_out_focus(struct stream_out *out)
629{
630 struct audio_device *adev = out->dev;
631
632 if (adev->adm_abandon_focus)
633 adev->adm_abandon_focus(adev->adm_data, out->handle);
634}
635
636static void release_in_focus(struct stream_in *in)
637{
638 struct audio_device *adev = in->dev;
639 if (adev->adm_abandon_focus)
640 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
641}
642
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530643static int parse_snd_card_status(struct str_parms *parms, int *card,
644 card_status_t *status)
645{
646 char value[32]={0};
647 char state[32]={0};
648
649 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
650 if (ret < 0)
651 return -1;
652
653 // sscanf should be okay as value is of max length 32.
654 // same as sizeof state.
655 if (sscanf(value, "%d,%s", card, state) < 2)
656 return -1;
657
658 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
659 CARD_STATUS_OFFLINE;
660 return 0;
661}
662
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700663static inline void adjust_frames_for_device_delay(struct stream_out *out,
664 uint32_t *dsp_frames) {
665 // Adjustment accounts for A2dp encoder latency with offload usecases
666 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800667 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700668 unsigned long offset =
669 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
670 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
671 }
672}
673
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700674static inline bool free_entry(void *key __unused,
675 void *value, void *context __unused)
676{
677 free(value);
678 return true;
679}
680
681static inline void free_map(Hashmap *map)
682{
683 if (map) {
684 hashmapForEach(map, free_entry, (void *) NULL);
685 hashmapFree(map);
686 }
687}
688
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800689static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700690 audio_patch_handle_t patch_handle)
691{
692 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
693 return;
694
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700695 struct audio_patch_info *p_info =
696 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
697 if (p_info) {
698 ALOGV("%s: Remove patch %d", __func__, patch_handle);
699 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
700 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700701 free(p_info);
702 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700703}
704
705static inline int io_streams_map_insert(struct audio_device *adev,
706 struct audio_stream *stream,
707 audio_io_handle_t handle,
708 audio_patch_handle_t patch_handle)
709{
710 struct audio_stream_info *s_info =
711 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
712
713 if (s_info == NULL) {
714 ALOGE("%s: Could not allocate stream info", __func__);
715 return -ENOMEM;
716 }
717 s_info->stream = stream;
718 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700719
720 pthread_mutex_lock(&adev->lock);
721 struct audio_stream_info *stream_info =
722 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700723 if (stream_info != NULL)
724 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800725 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700726 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
727 return 0;
728}
729
730static inline void io_streams_map_remove(struct audio_device *adev,
731 audio_io_handle_t handle)
732{
733 pthread_mutex_lock(&adev->lock);
734 struct audio_stream_info *s_info =
735 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700736 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800737 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700738 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800739 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700740 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800741done:
742 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 return;
744}
745
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800746static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 audio_patch_handle_t handle)
748{
749 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700750 p_info = (struct audio_patch_info *)
751 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700752 return p_info;
753}
754
vivek mehtaa76401a2015-04-24 14:12:15 -0700755__attribute__ ((visibility ("default")))
756bool audio_hw_send_gain_dep_calibration(int level) {
757 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700758 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700759
760 pthread_mutex_lock(&adev_init_lock);
761
762 if (adev != NULL && adev->platform != NULL) {
763 pthread_mutex_lock(&adev->lock);
764 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700765
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530766 // cache level info for any of the use case which
767 // was not started.
768 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700769
vivek mehtaa76401a2015-04-24 14:12:15 -0700770 pthread_mutex_unlock(&adev->lock);
771 } else {
772 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
773 }
774
775 pthread_mutex_unlock(&adev_init_lock);
776
777 return ret_val;
778}
779
Ashish Jain5106d362016-05-11 19:23:33 +0530780static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
781{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800782 bool gapless_enabled = false;
783 const char *mixer_ctl_name = "Compress Gapless Playback";
784 struct mixer_ctl *ctl;
785
786 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700787 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530788
789 /*Disable gapless if its AV playback*/
790 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800791
792 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
793 if (!ctl) {
794 ALOGE("%s: Could not get ctl for mixer cmd - %s",
795 __func__, mixer_ctl_name);
796 return -EINVAL;
797 }
798
799 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
800 ALOGE("%s: Could not set gapless mode %d",
801 __func__, gapless_enabled);
802 return -EINVAL;
803 }
804 return 0;
805}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700806
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700807__attribute__ ((visibility ("default")))
808int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
809 int table_size) {
810 int ret_val = 0;
811 ALOGV("%s: enter ... ", __func__);
812
813 pthread_mutex_lock(&adev_init_lock);
814 if (adev == NULL) {
815 ALOGW("%s: adev is NULL .... ", __func__);
816 goto done;
817 }
818
819 pthread_mutex_lock(&adev->lock);
820 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
821 pthread_mutex_unlock(&adev->lock);
822done:
823 pthread_mutex_unlock(&adev_init_lock);
824 ALOGV("%s: exit ... ", __func__);
825 return ret_val;
826}
827
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800828bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800829{
830 bool ret = false;
831 ALOGV("%s: enter ...", __func__);
832
833 pthread_mutex_lock(&adev_init_lock);
834
835 if (adev != NULL && adev->platform != NULL) {
836 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800837 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800838 pthread_mutex_unlock(&adev->lock);
839 }
840
841 pthread_mutex_unlock(&adev_init_lock);
842
843 ALOGV("%s: exit with ret %d", __func__, ret);
844 return ret;
845}
Aalique Grahame22e49102018-12-18 14:23:57 -0800846
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700847static bool is_supported_format(audio_format_t format)
848{
Eric Laurent86e17132013-09-12 17:49:30 -0700849 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530850 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530851 format == AUDIO_FORMAT_AAC_LC ||
852 format == AUDIO_FORMAT_AAC_HE_V1 ||
853 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530854 format == AUDIO_FORMAT_AAC_ADTS_LC ||
855 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
856 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530857 format == AUDIO_FORMAT_AAC_LATM_LC ||
858 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
859 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530860 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
861 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530862 format == AUDIO_FORMAT_PCM_FLOAT ||
863 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700864 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530865 format == AUDIO_FORMAT_AC3 ||
866 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700867 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530868 format == AUDIO_FORMAT_DTS ||
869 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800870 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530871 format == AUDIO_FORMAT_ALAC ||
872 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530873 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530874 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800875 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530876 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700877 format == AUDIO_FORMAT_APTX ||
878 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800879 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700880
881 return false;
882}
883
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700884static inline bool is_mmap_usecase(audio_usecase_t uc_id)
885{
886 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800887 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700888 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
889}
890
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700891static inline bool is_valid_volume(float left, float right)
892{
893 return ((left >= 0.0f && right >= 0.0f) ? true : false);
894}
895
Avinash Vaish71a8b972014-07-24 15:36:33 +0530896static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
897 struct audio_usecase *uc_info)
898{
899 struct listnode *node;
900 struct audio_usecase *usecase;
901
902 if (uc_info == NULL)
903 return -EINVAL;
904
905 /* Re-route all voice usecases on the shared backend other than the
906 specified usecase to new snd devices */
907 list_for_each(node, &adev->usecase_list) {
908 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800909 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530910 enable_audio_route(adev, usecase);
911 }
912 return 0;
913}
914
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530915static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530916{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530917 ALOGV("%s", __func__);
918 audio_route_apply_and_update_path(adev->audio_route,
919 "asrc-mode");
920 adev->asrc_mode_enabled = true;
921}
922
923static void disable_asrc_mode(struct audio_device *adev)
924{
925 ALOGV("%s", __func__);
926 audio_route_reset_and_update_path(adev->audio_route,
927 "asrc-mode");
928 adev->asrc_mode_enabled = false;
929}
930
931/*
932 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
933 * 44.1 or Native DSD backends are enabled for any of current use case.
934 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
935 * - Disable current mix path use case(Headphone backend) and re-enable it with
936 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
937 * e.g. Naitve DSD or Headphone 44.1 -> + 48
938 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530939static void check_and_set_asrc_mode(struct audio_device *adev,
940 struct audio_usecase *uc_info,
941 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530942{
943 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530944 int i, num_new_devices = 0;
945 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
946 /*
947 *Split snd device for new combo use case
948 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
949 */
950 if (platform_split_snd_device(adev->platform,
951 snd_device,
952 &num_new_devices,
953 split_new_snd_devices) == 0) {
954 for (i = 0; i < num_new_devices; i++)
955 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
956 } else {
957 int new_backend_idx = platform_get_backend_index(snd_device);
958 if (((new_backend_idx == HEADPHONE_BACKEND) ||
959 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
960 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
961 !adev->asrc_mode_enabled) {
962 struct listnode *node = NULL;
963 struct audio_usecase *uc = NULL;
964 struct stream_out *curr_out = NULL;
965 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
966 int i, num_devices, ret = 0;
967 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530968
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530969 list_for_each(node, &adev->usecase_list) {
970 uc = node_to_item(node, struct audio_usecase, list);
971 curr_out = (struct stream_out*) uc->stream.out;
972 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
973 /*
974 *Split snd device for existing combo use case
975 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
976 */
977 ret = platform_split_snd_device(adev->platform,
978 uc->out_snd_device,
979 &num_devices,
980 split_snd_devices);
981 if (ret < 0 || num_devices == 0) {
982 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
983 split_snd_devices[0] = uc->out_snd_device;
984 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800985 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530986 for (i = 0; i < num_devices; i++) {
987 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
988 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
989 if((new_backend_idx == HEADPHONE_BACKEND) &&
990 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
991 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
992 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
993 __func__);
994 enable_asrc_mode(adev);
995 break;
996 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
997 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
998 (usecase_backend_idx == HEADPHONE_BACKEND)) {
999 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
1000 __func__);
1001 disable_audio_route(adev, uc);
1002 disable_snd_device(adev, uc->out_snd_device);
1003 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1004 if (new_backend_idx == DSD_NATIVE_BACKEND)
1005 audio_route_apply_and_update_path(adev->audio_route,
1006 "hph-true-highquality-mode");
1007 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1008 (curr_out->bit_width >= 24))
1009 audio_route_apply_and_update_path(adev->audio_route,
1010 "hph-highquality-mode");
1011 enable_asrc_mode(adev);
1012 enable_snd_device(adev, uc->out_snd_device);
1013 enable_audio_route(adev, uc);
1014 break;
1015 }
1016 }
1017 // reset split devices count
1018 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001019 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301020 if (adev->asrc_mode_enabled)
1021 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301022 }
1023 }
1024 }
1025}
1026
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001027static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1028 struct audio_effect_config effect_config,
1029 unsigned int param_value)
1030{
1031 char mixer_ctl_name[] = "Audio Effect";
1032 struct mixer_ctl *ctl;
1033 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001034 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001035
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001036 if (in == NULL) {
1037 ALOGE("%s: active input stream is NULL", __func__);
1038 return -EINVAL;
1039 }
1040
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001041 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1042 if (!ctl) {
1043 ALOGE("%s: Could not get mixer ctl - %s",
1044 __func__, mixer_ctl_name);
1045 return -EINVAL;
1046 }
1047
1048 set_values[0] = 1; //0:Rx 1:Tx
1049 set_values[1] = in->app_type_cfg.app_type;
1050 set_values[2] = (long)effect_config.module_id;
1051 set_values[3] = (long)effect_config.instance_id;
1052 set_values[4] = (long)effect_config.param_id;
1053 set_values[5] = param_value;
1054
1055 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1056
1057 return 0;
1058
1059}
1060
1061static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1062 int effect_type, unsigned int *param_value)
1063{
1064 int ret = 0;
1065 struct audio_effect_config other_effect_config;
1066 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001067 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001068
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001069 if (in == NULL) {
1070 ALOGE("%s: active input stream is NULL", __func__);
1071 return -EINVAL;
1072 }
1073
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001074 usecase = get_usecase_from_list(adev, in->usecase);
1075 if (!usecase)
1076 return -EINVAL;
1077
1078 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1079 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1080 if (ret < 0) {
1081 ALOGE("%s Failed to get effect params %d", __func__, ret);
1082 return ret;
1083 }
1084
1085 if (module_id == other_effect_config.module_id) {
1086 //Same module id for AEC/NS. Values need to be combined
1087 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1088 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1089 *param_value |= other_effect_config.param_value;
1090 }
1091 }
1092
1093 return ret;
1094}
1095
1096static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301097{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001098 struct audio_effect_config effect_config;
1099 struct audio_usecase *usecase = NULL;
1100 int ret = 0;
1101 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001102 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001103
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001104 if(!voice_extn_is_dynamic_ecns_enabled())
1105 return ENOSYS;
1106
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001107 if (!in) {
1108 ALOGE("%s: Invalid input stream", __func__);
1109 return -EINVAL;
1110 }
1111
1112 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1113
1114 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001115 if (usecase == NULL) {
1116 ALOGE("%s: Could not find the usecase (%d) in the list",
1117 __func__, in->usecase);
1118 return -EINVAL;
1119 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001120
1121 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1122 if (ret < 0) {
1123 ALOGE("%s Failed to get module id %d", __func__, ret);
1124 return ret;
1125 }
1126 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1127 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1128
1129 if(enable)
1130 param_value = effect_config.param_value;
1131
1132 /*Special handling for AEC & NS effects Param values need to be
1133 updated if module ids are same*/
1134
1135 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1136 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1137 if (ret < 0)
1138 return ret;
1139 }
1140
1141 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1142
1143 return ret;
1144}
1145
1146static void check_and_enable_effect(struct audio_device *adev)
1147{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001148 if(!voice_extn_is_dynamic_ecns_enabled())
1149 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001150
Eric Laurent637e2d42018-11-15 12:24:31 -08001151 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001152
Eric Laurent637e2d42018-11-15 12:24:31 -08001153 if (in != NULL && !in->standby) {
1154 if (in->enable_aec)
1155 enable_disable_effect(adev, EFFECT_AEC, true);
1156
1157 if (in->enable_ns &&
1158 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1159 enable_disable_effect(adev, EFFECT_NS, true);
1160 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001161 }
1162}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001163
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001164int pcm_ioctl(struct pcm *pcm, int request, ...)
1165{
1166 va_list ap;
1167 void * arg;
1168 int pcm_fd = *(int*)pcm;
1169
1170 va_start(ap, request);
1171 arg = va_arg(ap, void *);
1172 va_end(ap);
1173
1174 return ioctl(pcm_fd, request, arg);
1175}
1176
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001177int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001178 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001179{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001180 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001181 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301182 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301183 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001184 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301185 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001186
1187 if (usecase == NULL)
1188 return -EINVAL;
1189
1190 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1191
Carter Hsu2e429db2019-05-14 18:50:52 +08001192 if (usecase->type == PCM_CAPTURE) {
1193 struct stream_in *in = usecase->stream.in;
1194 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001195 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001196
1197 if (in) {
1198 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001199 list_init(&out_devices);
1200 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001201 struct listnode *node;
1202 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1203 USECASE_AUDIO_PLAYBACK_VOIP);
1204 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001205 assign_devices(&out_devices,
1206 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001207 } else if (adev->primary_output &&
1208 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001209 assign_devices(&out_devices,
1210 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001211 } else {
1212 list_for_each(node, &adev->usecase_list) {
1213 uinfo = node_to_item(node, struct audio_usecase, list);
1214 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001215 assign_devices(&out_devices,
1216 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001217 break;
1218 }
1219 }
1220 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001221
1222 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001223 in->ec_opened = true;
1224 }
1225 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001226 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1227 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1228 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001229 snd_device = usecase->in_snd_device;
1230 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001231 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001232 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001233
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001234#ifdef DS1_DOLBY_DAP_ENABLED
1235 audio_extn_dolby_set_dmid(adev);
1236 audio_extn_dolby_set_endpoint(adev);
1237#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001238 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001239 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301240 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001241 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001242 if (audio_extn_is_maxx_audio_enabled())
1243 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301244 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301245 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1246 out = usecase->stream.out;
1247 if (out && out->compr)
1248 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1249 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301250
1251 if (usecase->type == PCM_CAPTURE) {
1252 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001253 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301254 ALOGD("%s: set custom mtmx params v1", __func__);
1255 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1256 }
1257 } else {
1258 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1259 }
Manish Dewangan58229382017-02-02 15:48:41 +05301260
Andy Hung756ecc12018-10-19 17:47:12 -07001261 // we shouldn't truncate mixer_path
1262 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1263 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1264 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001265 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001266 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301267 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1268 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1269 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1270 if (parms) {
1271 audio_extn_fm_set_parameters(adev, parms);
1272 str_parms_destroy(parms);
1273 }
1274 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275 ALOGV("%s: exit", __func__);
1276 return 0;
1277}
1278
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001279int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001280 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001282 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001283 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301284 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001285
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301286 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001287 return -EINVAL;
1288
1289 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301290 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001291 snd_device = usecase->in_snd_device;
1292 else
1293 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001294
1295 /* disable island and power mode on supported device for voice call */
1296 if (usecase->type == VOICE_CALL) {
1297 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1298 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1299 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1300 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1301 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1302 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
1303 ALOGD("%s: disable island cfg and power mode in voice tx path",
1304 __func__);
1305 }
1306 }
1307 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1308 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1309 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1310 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1311 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1312 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1313 ALOGD("%s: disable island cfg and power mode in voice rx path",
1314 __func__);
1315 }
1316 }
1317 }
1318
Andy Hung756ecc12018-10-19 17:47:12 -07001319 // we shouldn't truncate mixer_path
1320 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1321 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1322 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001323 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001324 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001325 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001326 if (usecase->type == PCM_CAPTURE) {
1327 struct stream_in *in = usecase->stream.in;
1328 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001329 struct listnode out_devices;
1330 list_init(&out_devices);
1331 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001332 in->ec_opened = false;
1333 }
1334 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001335 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301336 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301337
1338 if (usecase->type == PCM_CAPTURE) {
1339 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001340 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301341 ALOGD("%s: reset custom mtmx params v1", __func__);
1342 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1343 }
1344 } else {
1345 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1346 }
1347
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001348 if ((usecase->type == PCM_PLAYBACK) &&
1349 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301350 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001352 ALOGV("%s: exit", __func__);
1353 return 0;
1354}
1355
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001356int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001357 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001358{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301359 int i, num_devices = 0;
1360 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001361 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1362
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001363 if (snd_device < SND_DEVICE_MIN ||
1364 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001365 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001366 return -EINVAL;
1367 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001368
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001369 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001370 ALOGE("%s: Invalid sound device returned", __func__);
1371 return -EINVAL;
1372 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001373
1374 adev->snd_dev_ref_cnt[snd_device]++;
1375
1376 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1377 (platform_split_snd_device(adev->platform,
1378 snd_device,
1379 &num_devices,
1380 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001381 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001382 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001383 return 0;
1384 }
1385
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001386 if (audio_extn_spkr_prot_is_enabled())
1387 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001388
Aalique Grahame22e49102018-12-18 14:23:57 -08001389 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1390
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001391 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1392 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001393 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1394 goto err;
1395 }
1396 audio_extn_dev_arbi_acquire(snd_device);
1397 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001398 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001399 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001400 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001401 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001402 } else if (platform_split_snd_device(adev->platform,
1403 snd_device,
1404 &num_devices,
1405 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301406 for (i = 0; i < num_devices; i++) {
1407 enable_snd_device(adev, new_snd_devices[i]);
1408 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001409 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001410 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001411 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301412
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001413 /* enable island and power mode on supported device */
1414 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1415 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1416 platform_set_island_cfg_on_device(adev, snd_device, true);
1417 platform_set_power_mode_on_device(adev, snd_device, true);
1418 ALOGD("%s: enable island cfg and power mode on: %s",
1419 __func__, device_name);
1420 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301421
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001422 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1423 (audio_extn_a2dp_start_playback() < 0)) {
1424 ALOGE(" fail to configure A2dp Source control path ");
1425 goto err;
1426 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001427
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001428 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1429 (audio_extn_a2dp_start_capture() < 0)) {
1430 ALOGE(" fail to configure A2dp Sink control path ");
1431 goto err;
1432 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301433
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001434 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1435 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1436 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1437 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1438 ALOGE(" fail to configure sco control path ");
1439 goto err;
1440 }
Zhou Song12c29502019-03-16 10:37:18 +08001441 }
1442
Zhou Song331c8e52019-08-26 14:16:12 +08001443 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001444 /* due to the possibility of calibration overwrite between listen
1445 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001446 audio_extn_sound_trigger_update_device_status(snd_device,
1447 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301448 audio_extn_listen_update_device_status(snd_device,
1449 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001450 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001451 audio_extn_sound_trigger_update_device_status(snd_device,
1452 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301453 audio_extn_listen_update_device_status(snd_device,
1454 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001455 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001456 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001457 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001458 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301459
1460 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1461 !adev->native_playback_enabled &&
1462 audio_is_true_native_stream_active(adev)) {
1463 ALOGD("%s: %d: napb: enabling native mode in hardware",
1464 __func__, __LINE__);
1465 audio_route_apply_and_update_path(adev->audio_route,
1466 "true-native-mode");
1467 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301468 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301469 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1470 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001471 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001472 ALOGD("%s: init ec ref loopback", __func__);
1473 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1474 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001476 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001477err:
1478 adev->snd_dev_ref_cnt[snd_device]--;
1479 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480}
1481
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001482int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001483 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301485 int i, num_devices = 0;
1486 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001487 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1488
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001489 if (snd_device < SND_DEVICE_MIN ||
1490 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001491 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001492 return -EINVAL;
1493 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001494
1495 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1496 ALOGE("%s: Invalid sound device returned", __func__);
1497 return -EINVAL;
1498 }
1499
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001500 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1501 ALOGE("%s: device ref cnt is already 0", __func__);
1502 return -EINVAL;
1503 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001504
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001505 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001506
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001507
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001508 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001509 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301510
Aalique Grahame22e49102018-12-18 14:23:57 -08001511 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1512
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001513 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1514 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001515 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001516
1517 // when speaker device is disabled, reset swap.
1518 // will be renabled on usecase start
1519 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001520 } else if (platform_split_snd_device(adev->platform,
1521 snd_device,
1522 &num_devices,
1523 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301524 for (i = 0; i < num_devices; i++) {
1525 disable_snd_device(adev, new_snd_devices[i]);
1526 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001527 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001528 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001529 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001530 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001531
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001532 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301533 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001534 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001535 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001536 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001537 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301538 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001539 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301540 adev->native_playback_enabled) {
1541 ALOGD("%s: %d: napb: disabling native mode in hardware",
1542 __func__, __LINE__);
1543 audio_route_reset_and_update_path(adev->audio_route,
1544 "true-native-mode");
1545 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001546 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301547 adev->asrc_mode_enabled) {
1548 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301549 disable_asrc_mode(adev);
1550 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001551 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301552 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001553 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001554 ALOGD("%s: deinit ec ref loopback", __func__);
1555 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1556 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001557
1558 audio_extn_utils_release_snd_device(snd_device);
1559 } else {
1560 if (platform_split_snd_device(adev->platform,
1561 snd_device,
1562 &num_devices,
1563 new_snd_devices) == 0) {
1564 for (i = 0; i < num_devices; i++) {
1565 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1566 }
1567 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001568 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001570 return 0;
1571}
1572
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001573/*
1574 legend:
1575 uc - existing usecase
1576 new_uc - new usecase
1577 d1, d11, d2 - SND_DEVICE enums
1578 a1, a2 - corresponding ANDROID device enums
1579 B1, B2 - backend strings
1580
1581case 1
1582 uc->dev d1 (a1) B1
1583 new_uc->dev d1 (a1), d2 (a2) B1, B2
1584
1585 resolution: disable and enable uc->dev on d1
1586
1587case 2
1588 uc->dev d1 (a1) B1
1589 new_uc->dev d11 (a1) B1
1590
1591 resolution: need to switch uc since d1 and d11 are related
1592 (e.g. speaker and voice-speaker)
1593 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1594
1595case 3
1596 uc->dev d1 (a1) B1
1597 new_uc->dev d2 (a2) B2
1598
1599 resolution: no need to switch uc
1600
1601case 4
1602 uc->dev d1 (a1) B1
1603 new_uc->dev d2 (a2) B1
1604
1605 resolution: disable enable uc-dev on d2 since backends match
1606 we cannot enable two streams on two different devices if they
1607 share the same backend. e.g. if offload is on speaker device using
1608 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1609 using the same backend, offload must also be switched to voice-handset.
1610
1611case 5
1612 uc->dev d1 (a1) B1
1613 new_uc->dev d1 (a1), d2 (a2) B1
1614
1615 resolution: disable enable uc-dev on d2 since backends match
1616 we cannot enable two streams on two different devices if they
1617 share the same backend.
1618
1619case 6
1620 uc->dev d1 (a1) B1
1621 new_uc->dev d2 (a1) B2
1622
1623 resolution: no need to switch
1624
1625case 7
1626 uc->dev d1 (a1), d2 (a2) B1, B2
1627 new_uc->dev d1 (a1) B1
1628
1629 resolution: no need to switch
1630
Zhou Song4ba65882018-07-09 14:48:07 +08001631case 8
1632 uc->dev d1 (a1) B1
1633 new_uc->dev d11 (a1), d2 (a2) B1, B2
1634 resolution: compared to case 1, for this case, d1 and d11 are related
1635 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001636*/
1637static snd_device_t derive_playback_snd_device(void * platform,
1638 struct audio_usecase *uc,
1639 struct audio_usecase *new_uc,
1640 snd_device_t new_snd_device)
1641{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001642 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001643
1644 snd_device_t d1 = uc->out_snd_device;
1645 snd_device_t d2 = new_snd_device;
1646
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001647 list_init(&a1);
1648 list_init(&a2);
1649
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301650 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301651 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001652 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1653 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301654 break;
1655 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001656 assign_devices(&a1, &uc->stream.out->device_list);
1657 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301658 break;
1659 }
1660
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001661 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001662 if (!compare_devices(&a1, &a2) &&
1663 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001664 snd_device_t d3[2];
1665 int num_devices = 0;
1666 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001667 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001668 &num_devices,
1669 d3);
1670 if (ret < 0) {
1671 if (ret != -ENOSYS) {
1672 ALOGW("%s failed to split snd_device %d",
1673 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001674 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001675 }
1676 goto end;
1677 }
1678
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001679 if (platform_check_backends_match(d3[0], d3[1])) {
1680 return d2; // case 5
1681 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001682 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301683 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001684 // check if d1 is related to any of d3's
1685 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001686 return d1; // case 1
1687 else
1688 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001689 }
1690 } else {
1691 if (platform_check_backends_match(d1, d2)) {
1692 return d2; // case 2, 4
1693 } else {
1694 return d1; // case 6, 3
1695 }
1696 }
1697
1698end:
1699 return d2; // return whatever was calculated before.
1700}
1701
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001702static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301703 struct audio_usecase *uc_info,
1704 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001705{
1706 struct listnode *node;
1707 struct audio_usecase *usecase;
1708 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301709 snd_device_t uc_derive_snd_device;
1710 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001711 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1712 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001713 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301714 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001715 /*
1716 * This function is to make sure that all the usecases that are active on
1717 * the hardware codec backend are always routed to any one device that is
1718 * handled by the hardware codec.
1719 * For example, if low-latency and deep-buffer usecases are currently active
1720 * on speaker and out_set_parameters(headset) is received on low-latency
1721 * output, then we have to make sure deep-buffer is also switched to headset,
1722 * because of the limitation that both the devices cannot be enabled
1723 * at the same time as they share the same backend.
1724 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001725 /*
1726 * This call is to check if we need to force routing for a particular stream
1727 * If there is a backend configuration change for the device when a
1728 * new stream starts, then ADM needs to be closed and re-opened with the new
1729 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001730 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001731 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001732 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1733 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301734 /* For a2dp device reconfigure all active sessions
1735 * with new AFE encoder format based on a2dp state
1736 */
1737 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1738 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1739 audio_extn_a2dp_is_force_device_switch()) {
1740 force_routing = true;
1741 force_restart_session = true;
1742 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001743
1744 /*
1745 * Island cfg and power mode config needs to set before AFE port start.
1746 * Set force routing in case of voice device was enable before.
1747 */
1748 if (uc_info->type == VOICE_CALL &&
1749 voice_extn_is_voice_power_mode_supported() &&
1750 platform_check_and_update_island_power_status(adev->platform,
1751 uc_info,
1752 snd_device)) {
1753 force_routing = true;
1754 ALOGD("%s:becf: force routing %d for power mode supported device",
1755 __func__, force_routing);
1756 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301757 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1758
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001759 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001760 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001761 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001762 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1763 switch_device[i] = false;
1764
1765 list_for_each(node, &adev->usecase_list) {
1766 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001767
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301768 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1769 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301770 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301771 platform_get_snd_device_name(usecase->out_snd_device),
1772 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301773 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1774 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301775 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1776 usecase, uc_info, snd_device);
1777 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001778 (is_codec_backend_out_device_type(&usecase->device_list) ||
1779 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1780 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1781 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1782 is_a2dp_out_device_type(&usecase->device_list) ||
1783 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301784 ((force_restart_session) ||
1785 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301786 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1787 __func__, use_case_table[usecase->id],
1788 platform_get_snd_device_name(usecase->out_snd_device));
1789 disable_audio_route(adev, usecase);
1790 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301791 /* Enable existing usecase on derived playback device */
1792 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301793 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301794 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795 }
1796 }
1797
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301798 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1799 num_uc_to_switch);
1800
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001801 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001802 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001803
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301804 /* Make sure the previous devices to be disabled first and then enable the
1805 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001806 list_for_each(node, &adev->usecase_list) {
1807 usecase = node_to_item(node, struct audio_usecase, list);
1808 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001809 /* Check if output sound device to be switched can be split and if any
1810 of the split devices match with derived sound device */
1811 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1812 &num_devices, split_snd_devices) == 0) {
1813 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1814 for (i = 0; i < num_devices; i++) {
1815 /* Disable devices that do not match with derived sound device */
1816 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1817 disable_snd_device(adev, split_snd_devices[i]);
1818 }
1819 } else {
1820 disable_snd_device(adev, usecase->out_snd_device);
1821 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822 }
1823 }
1824
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001825 list_for_each(node, &adev->usecase_list) {
1826 usecase = node_to_item(node, struct audio_usecase, list);
1827 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001828 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1829 &num_devices, split_snd_devices) == 0) {
1830 /* Enable derived sound device only if it does not match with
1831 one of the split sound devices. This is because the matching
1832 sound device was not disabled */
1833 bool should_enable = true;
1834 for (i = 0; i < num_devices; i++) {
1835 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1836 should_enable = false;
1837 break;
1838 }
1839 }
1840 if (should_enable)
1841 enable_snd_device(adev, derive_snd_device[usecase->id]);
1842 } else {
1843 enable_snd_device(adev, derive_snd_device[usecase->id]);
1844 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001845 }
1846 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001847
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001848 /* Re-route all the usecases on the shared backend other than the
1849 specified usecase to new snd devices */
1850 list_for_each(node, &adev->usecase_list) {
1851 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301852 /* Update the out_snd_device only before enabling the audio route */
1853 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301854 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301855 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301856 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301857 use_case_table[usecase->id],
1858 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001859 /* Update voc calibration before enabling VoIP route */
1860 if (usecase->type == VOIP_CALL)
1861 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001862 usecase->out_snd_device,
1863 platform_get_input_snd_device(
1864 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301865 &uc_info->device_list,
1866 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301867 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301868 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001869 out_set_voip_volume(&usecase->stream.out->stream,
1870 usecase->stream.out->volume_l,
1871 usecase->stream.out->volume_r);
1872 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301873 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001874 }
1875 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001876 }
1877}
1878
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301879static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001880 struct audio_usecase *uc_info,
1881 snd_device_t snd_device)
1882{
1883 struct listnode *node;
1884 struct audio_usecase *usecase;
1885 bool switch_device[AUDIO_USECASE_MAX];
1886 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001887 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001888 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001889
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301890 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1891 snd_device);
1892 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301893
1894 /*
1895 * Make sure out devices is checked against out codec backend device and
1896 * also in devices against in codec backend. Checking out device against in
1897 * codec backend or vice versa causes issues.
1898 */
1899 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001900 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001901
1902 /*
1903 * Island cfg and power mode config needs to set before AFE port start.
1904 * Set force routing in case of voice device was enable before.
1905 */
1906
1907 if (uc_info->type == VOICE_CALL &&
1908 voice_extn_is_voice_power_mode_supported() &&
1909 platform_check_and_update_island_power_status(adev->platform,
1910 uc_info,
1911 snd_device)) {
1912 force_routing = true;
1913 ALOGD("%s:becf: force routing %d for power mode supported device",
1914 __func__, force_routing);
1915 }
1916
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001917 /*
1918 * This function is to make sure that all the active capture usecases
1919 * are always routed to the same input sound device.
1920 * For example, if audio-record and voice-call usecases are currently
1921 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1922 * is received for voice call then we have to make sure that audio-record
1923 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1924 * because of the limitation that two devices cannot be enabled
1925 * at the same time if they share the same backend.
1926 */
1927 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1928 switch_device[i] = false;
1929
1930 list_for_each(node, &adev->usecase_list) {
1931 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301932 /*
1933 * TODO: Enhance below condition to handle BT sco/USB multi recording
1934 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301935
1936 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1937 (usecase->in_snd_device != snd_device || force_routing));
1938 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1939 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1940 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001941 ((backend_check_cond &&
1942 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001943 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001944 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001945 is_single_device_type_equal(&usecase->device_list,
1946 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001947 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001948 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001949 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301950 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001951 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001952 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001953 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001954 switch_device[usecase->id] = true;
1955 num_uc_to_switch++;
1956 }
1957 }
1958
1959 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001960 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001961
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301962 /* Make sure the previous devices to be disabled first and then enable the
1963 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001964 list_for_each(node, &adev->usecase_list) {
1965 usecase = node_to_item(node, struct audio_usecase, list);
1966 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001967 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001968 }
1969 }
1970
1971 list_for_each(node, &adev->usecase_list) {
1972 usecase = node_to_item(node, struct audio_usecase, list);
1973 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001974 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001975 }
1976 }
1977
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001978 /* Re-route all the usecases on the shared backend other than the
1979 specified usecase to new snd devices */
1980 list_for_each(node, &adev->usecase_list) {
1981 usecase = node_to_item(node, struct audio_usecase, list);
1982 /* Update the in_snd_device only before enabling the audio route */
1983 if (switch_device[usecase->id] ) {
1984 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001985 if (usecase->type != VOICE_CALL) {
1986 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301987 if (usecase->type == VOIP_CALL) {
1988 snd_device_t voip_snd_device;
1989 voip_snd_device = platform_get_output_snd_device(adev->platform,
1990 uc_info->stream.out,
1991 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08001992 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301993 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08001994 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05301995 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05301996 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001997 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001998 }
1999 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002000 }
2001}
2002
Mingming Yin3a941d42016-02-17 18:08:05 -08002003static void reset_hdmi_sink_caps(struct stream_out *out) {
2004 int i = 0;
2005
2006 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2007 out->supported_channel_masks[i] = 0;
2008 }
2009 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2010 out->supported_formats[i] = 0;
2011 }
2012 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2013 out->supported_sample_rates[i] = 0;
2014 }
2015}
2016
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002018static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019{
Mingming Yin3a941d42016-02-17 18:08:05 -08002020 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002021 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2022 out->extconn.cs.controller,
2023 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024
Mingming Yin3a941d42016-02-17 18:08:05 -08002025 reset_hdmi_sink_caps(out);
2026
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002027 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002028 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002029 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002030 out->extconn.cs.stream);
2031 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002032 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002033 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002034 }
2035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002038 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002039 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002040 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2041 case 6:
2042 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2043 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2044 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2045 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2046 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2047 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048 break;
2049 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002050 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002051 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 break;
2053 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002054
2055 // check channel format caps
2056 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002057 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2058 out->extconn.cs.controller,
2059 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002060 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2061 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2062 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2063 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2064 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2065 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2066 }
2067
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002068 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2069 out->extconn.cs.controller,
2070 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002071 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2072 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2073 }
2074
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002075 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2076 out->extconn.cs.controller,
2077 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002078 ALOGV(":%s HDMI supports DTS format", __func__);
2079 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2080 }
2081
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002082 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2083 out->extconn.cs.controller,
2084 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002085 ALOGV(":%s HDMI supports DTS HD format", __func__);
2086 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2087 }
2088
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002089 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2090 out->extconn.cs.controller,
2091 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002092 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2093 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2094 }
2095
Mingming Yin3a941d42016-02-17 18:08:05 -08002096
2097 // check sample rate caps
2098 i = 0;
2099 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002100 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2101 out->extconn.cs.controller,
2102 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002103 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2104 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2105 }
2106 }
2107
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002108 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109}
2110
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002111static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2112 uint32_t *supported_sample_rates __unused,
2113 uint32_t max_rates __unused)
2114{
2115 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2116 supported_sample_rates,
2117 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302118 ssize_t i = 0;
2119
2120 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002121 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2122 supported_sample_rates[i]);
2123 }
2124 return count;
2125}
2126
2127static inline int read_usb_sup_channel_masks(bool is_playback,
2128 audio_channel_mask_t *supported_channel_masks,
2129 uint32_t max_masks)
2130{
2131 int channels = audio_extn_usb_get_max_channels(is_playback);
2132 int channel_count;
2133 uint32_t num_masks = 0;
2134 if (channels > MAX_HIFI_CHANNEL_COUNT)
2135 channels = MAX_HIFI_CHANNEL_COUNT;
2136
2137 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002138 // start from 2 channels as framework currently doesn't support mono.
2139 if (channels >= FCC_2) {
2140 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2141 }
2142 for (channel_count = FCC_2;
2143 channel_count <= channels && num_masks < max_masks;
2144 ++channel_count) {
2145 supported_channel_masks[num_masks++] =
2146 audio_channel_mask_for_index_assignment_from_count(channel_count);
2147 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002148 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002149 // For capture we report all supported channel masks from 1 channel up.
2150 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002151 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2152 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002153 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2154 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2155 if (channel_count <= FCC_2) {
2156 mask = audio_channel_in_mask_from_count(channel_count);
2157 supported_channel_masks[num_masks++] = mask;
2158 }
2159 const audio_channel_mask_t index_mask =
2160 audio_channel_mask_for_index_assignment_from_count(channel_count);
2161 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2162 supported_channel_masks[num_masks++] = index_mask;
2163 }
2164 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002165 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302166
vincenttewf51c94e2019-05-07 10:28:53 +08002167 for (size_t i = 0; i < num_masks; ++i) {
2168 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2169 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302170 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002171 return num_masks;
2172}
2173
2174static inline int read_usb_sup_formats(bool is_playback __unused,
2175 audio_format_t *supported_formats,
2176 uint32_t max_formats __unused)
2177{
2178 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2179 switch (bitwidth) {
2180 case 24:
2181 // XXX : usb.c returns 24 for s24 and s24_le?
2182 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2183 break;
2184 case 32:
2185 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2186 break;
2187 case 16:
2188 default :
2189 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2190 break;
2191 }
2192 ALOGV("%s: %s supported format %d", __func__,
2193 is_playback ? "P" : "C", bitwidth);
2194 return 1;
2195}
2196
2197static inline int read_usb_sup_params_and_compare(bool is_playback,
2198 audio_format_t *format,
2199 audio_format_t *supported_formats,
2200 uint32_t max_formats,
2201 audio_channel_mask_t *mask,
2202 audio_channel_mask_t *supported_channel_masks,
2203 uint32_t max_masks,
2204 uint32_t *rate,
2205 uint32_t *supported_sample_rates,
2206 uint32_t max_rates) {
2207 int ret = 0;
2208 int num_formats;
2209 int num_masks;
2210 int num_rates;
2211 int i;
2212
2213 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2214 max_formats);
2215 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2216 max_masks);
2217
2218 num_rates = read_usb_sup_sample_rates(is_playback,
2219 supported_sample_rates, max_rates);
2220
2221#define LUT(table, len, what, dflt) \
2222 for (i=0; i<len && (table[i] != what); i++); \
2223 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2224
2225 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2226 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2227 LUT(supported_sample_rates, num_rates, *rate, 0);
2228
2229#undef LUT
2230 return ret < 0 ? -EINVAL : 0; // HACK TBD
2231}
2232
Alexy Josephb1379942016-01-29 15:49:38 -08002233audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002234 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002235{
2236 struct audio_usecase *usecase;
2237 struct listnode *node;
2238
2239 list_for_each(node, &adev->usecase_list) {
2240 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002241 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002242 ALOGV("%s: usecase id %d", __func__, usecase->id);
2243 return usecase->id;
2244 }
2245 }
2246 return USECASE_INVALID;
2247}
2248
Alexy Josephb1379942016-01-29 15:49:38 -08002249struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002250 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002251{
2252 struct audio_usecase *usecase;
2253 struct listnode *node;
2254
2255 list_for_each(node, &adev->usecase_list) {
2256 usecase = node_to_item(node, struct audio_usecase, list);
2257 if (usecase->id == uc_id)
2258 return usecase;
2259 }
2260 return NULL;
2261}
2262
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302263/*
2264 * is a true native playback active
2265 */
2266bool audio_is_true_native_stream_active(struct audio_device *adev)
2267{
2268 bool active = false;
2269 int i = 0;
2270 struct listnode *node;
2271
2272 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2273 ALOGV("%s:napb: not in true mode or non hdphones device",
2274 __func__);
2275 active = false;
2276 goto exit;
2277 }
2278
2279 list_for_each(node, &adev->usecase_list) {
2280 struct audio_usecase *uc;
2281 uc = node_to_item(node, struct audio_usecase, list);
2282 struct stream_out *curr_out =
2283 (struct stream_out*) uc->stream.out;
2284
2285 if (curr_out && PCM_PLAYBACK == uc->type) {
2286 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2287 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2288 uc->id, curr_out->sample_rate,
2289 curr_out->bit_width,
2290 platform_get_snd_device_name(uc->out_snd_device));
2291
2292 if (is_offload_usecase(uc->id) &&
2293 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2294 active = true;
2295 ALOGD("%s:napb:native stream detected", __func__);
2296 }
2297 }
2298 }
2299exit:
2300 return active;
2301}
2302
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002303uint32_t adev_get_dsp_bit_width_enforce_mode()
2304{
2305 if (adev == NULL) {
2306 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2307 return 0;
2308 }
2309 return adev->dsp_bit_width_enforce_mode;
2310}
2311
2312static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2313{
2314 char value[PROPERTY_VALUE_MAX];
2315 int trial;
2316 uint32_t dsp_bit_width_enforce_mode = 0;
2317
2318 if (!mixer) {
2319 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2320 __func__);
2321 return 0;
2322 }
2323
2324 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2325 value, NULL) > 0) {
2326 trial = atoi(value);
2327 switch (trial) {
2328 case 16:
2329 dsp_bit_width_enforce_mode = 16;
2330 break;
2331 case 24:
2332 dsp_bit_width_enforce_mode = 24;
2333 break;
2334 case 32:
2335 dsp_bit_width_enforce_mode = 32;
2336 break;
2337 default:
2338 dsp_bit_width_enforce_mode = 0;
2339 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2340 break;
2341 }
2342 }
2343
2344 return dsp_bit_width_enforce_mode;
2345}
2346
2347static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2348 uint32_t enforce_mode,
2349 bool enable)
2350{
2351 struct mixer_ctl *ctl = NULL;
2352 const char *mixer_ctl_name = "ASM Bit Width";
2353 uint32_t asm_bit_width_mode = 0;
2354
2355 if (enforce_mode == 0) {
2356 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2357 return;
2358 }
2359
2360 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2361 if (!ctl) {
2362 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2363 __func__, mixer_ctl_name);
2364 return;
2365 }
2366
2367 if (enable)
2368 asm_bit_width_mode = enforce_mode;
2369 else
2370 asm_bit_width_mode = 0;
2371
2372 ALOGV("%s DSP bit width feature status is %d width=%d",
2373 __func__, enable, asm_bit_width_mode);
2374 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2375 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2376 asm_bit_width_mode);
2377
2378 return;
2379}
2380
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302381/*
2382 * if native DSD playback active
2383 */
2384bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2385{
2386 bool active = false;
2387 struct listnode *node = NULL;
2388 struct audio_usecase *uc = NULL;
2389 struct stream_out *curr_out = NULL;
2390
2391 list_for_each(node, &adev->usecase_list) {
2392 uc = node_to_item(node, struct audio_usecase, list);
2393 curr_out = (struct stream_out*) uc->stream.out;
2394
2395 if (curr_out && PCM_PLAYBACK == uc->type &&
2396 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2397 active = true;
2398 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302399 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302400 }
2401 }
2402 return active;
2403}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302404
2405static bool force_device_switch(struct audio_usecase *usecase)
2406{
2407 bool ret = false;
2408 bool is_it_true_mode = false;
2409
Zhou Song30f2c3e2018-02-08 14:02:15 +08002410 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302411 usecase->type == TRANSCODE_LOOPBACK_RX ||
2412 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002413 return false;
2414 }
2415
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002416 if(usecase->stream.out == NULL) {
2417 ALOGE("%s: stream.out is NULL", __func__);
2418 return false;
2419 }
2420
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302421 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002422 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002423 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2424 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302425 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2426 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2427 (!is_it_true_mode && adev->native_playback_enabled)){
2428 ret = true;
2429 ALOGD("napb: time to toggle native mode");
2430 }
2431 }
2432
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302433 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302434 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2435 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002436 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302437 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302438 ALOGD("Force a2dp device switch to update new encoder config");
2439 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002440 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302441
Florian Pfister1a84f312018-07-19 14:38:18 +02002442 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302443 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2444 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002445 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302446 return ret;
2447}
2448
Aalique Grahame22e49102018-12-18 14:23:57 -08002449static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2450{
2451 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2452}
2453
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302454bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2455{
2456 bool ret=false;
2457 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002458 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2459 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302460 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2461 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002462 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302463 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002464 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2465 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302466 ret = true;
2467
2468 return ret;
2469}
2470
2471bool is_a2dp_device(snd_device_t out_snd_device)
2472{
2473 bool ret=false;
2474 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2475 ret = true;
2476
2477 return ret;
2478}
2479
2480bool is_bt_soc_on(struct audio_device *adev)
2481{
2482 struct mixer_ctl *ctl;
2483 char *mixer_ctl_name = "BT SOC status";
2484 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2485 bool bt_soc_status = true;
2486 if (!ctl) {
2487 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2488 __func__, mixer_ctl_name);
2489 /*This is to ensure we dont break targets which dont have the kernel change*/
2490 return true;
2491 }
2492 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2493 ALOGD("BT SOC status: %d",bt_soc_status);
2494 return bt_soc_status;
2495}
2496
Zhou Song331c8e52019-08-26 14:16:12 +08002497static int configure_btsco_sample_rate(snd_device_t snd_device)
2498{
2499 struct mixer_ctl *ctl = NULL;
2500 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2501 char *rate_str = NULL;
2502 bool is_rx_dev = true;
2503
2504 if (is_btsco_device(snd_device, snd_device)) {
2505 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2506 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2507 if (!ctl_sr_tx || !ctl_sr_rx) {
2508 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2509 if (!ctl_sr)
2510 return -ENOSYS;
2511 }
2512
2513 switch (snd_device) {
2514 case SND_DEVICE_OUT_BT_SCO:
2515 rate_str = "KHZ_8";
2516 break;
2517 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2518 case SND_DEVICE_IN_BT_SCO_MIC:
2519 rate_str = "KHZ_8";
2520 is_rx_dev = false;
2521 break;
2522 case SND_DEVICE_OUT_BT_SCO_WB:
2523 rate_str = "KHZ_16";
2524 break;
2525 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2526 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2527 rate_str = "KHZ_16";
2528 is_rx_dev = false;
2529 break;
2530 default:
2531 return 0;
2532 }
2533
2534 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2535 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2536 return -ENOSYS;
2537 }
2538 return 0;
2539}
2540
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302541int out_standby_l(struct audio_stream *stream);
2542
Eric Laurent637e2d42018-11-15 12:24:31 -08002543struct stream_in *adev_get_active_input(const struct audio_device *adev)
2544{
2545 struct listnode *node;
2546 struct stream_in *last_active_in = NULL;
2547
2548 /* Get last added active input.
2549 * TODO: We may use a priority mechanism to pick highest priority active source */
2550 list_for_each(node, &adev->usecase_list)
2551 {
2552 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2553 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2554 last_active_in = usecase->stream.in;
2555 }
2556
2557 return last_active_in;
2558}
2559
2560struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2561{
2562 struct listnode *node;
2563
2564 /* First check active inputs with voice communication source and then
2565 * any input if audio mode is in communication */
2566 list_for_each(node, &adev->usecase_list)
2567 {
2568 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2569 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2570 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2571 return usecase->stream.in;
2572 }
2573 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2574 return adev_get_active_input(adev);
2575
2576 return NULL;
2577}
2578
Carter Hsu2e429db2019-05-14 18:50:52 +08002579/*
2580 * Aligned with policy.h
2581 */
2582static inline int source_priority(int inputSource)
2583{
2584 switch (inputSource) {
2585 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2586 return 9;
2587 case AUDIO_SOURCE_CAMCORDER:
2588 return 8;
2589 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2590 return 7;
2591 case AUDIO_SOURCE_UNPROCESSED:
2592 return 6;
2593 case AUDIO_SOURCE_MIC:
2594 return 5;
2595 case AUDIO_SOURCE_ECHO_REFERENCE:
2596 return 4;
2597 case AUDIO_SOURCE_FM_TUNER:
2598 return 3;
2599 case AUDIO_SOURCE_VOICE_RECOGNITION:
2600 return 2;
2601 case AUDIO_SOURCE_HOTWORD:
2602 return 1;
2603 default:
2604 break;
2605 }
2606 return 0;
2607}
2608
2609static struct stream_in *get_priority_input(struct audio_device *adev)
2610{
2611 struct listnode *node;
2612 struct audio_usecase *usecase;
2613 int last_priority = 0, priority;
2614 struct stream_in *priority_in = NULL;
2615 struct stream_in *in;
2616
2617 list_for_each(node, &adev->usecase_list) {
2618 usecase = node_to_item(node, struct audio_usecase, list);
2619 if (usecase->type == PCM_CAPTURE) {
2620 in = usecase->stream.in;
2621 if (!in)
2622 continue;
2623 priority = source_priority(in->source);
2624
2625 if (priority > last_priority) {
2626 last_priority = priority;
2627 priority_in = in;
2628 }
2629 }
2630 }
2631 return priority_in;
2632}
2633
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002634int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002636 snd_device_t out_snd_device = SND_DEVICE_NONE;
2637 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002638 struct audio_usecase *usecase = NULL;
2639 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002640 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002641 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302642 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002643 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002644 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302646 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2647
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002648 usecase = get_usecase_from_list(adev, uc_id);
2649 if (usecase == NULL) {
2650 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2651 return -EINVAL;
2652 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002654 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002655 (usecase->type == VOIP_CALL) ||
2656 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302657 if(usecase->stream.out == NULL) {
2658 ALOGE("%s: stream.out is NULL", __func__);
2659 return -EINVAL;
2660 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002661 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002662 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2663 uc_id);
2664 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2665 uc_id);
2666 } else {
2667 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302668 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002669 in_snd_device = platform_get_input_snd_device(adev->platform,
2670 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302671 &usecase->stream.out->device_list,
2672 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002673 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002674 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302675 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302676 if (usecase->stream.inout == NULL) {
2677 ALOGE("%s: stream.inout is NULL", __func__);
2678 return -EINVAL;
2679 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002680 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302681 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2682 stream_out.format = usecase->stream.inout->out_config.format;
2683 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302684 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002685 assign_devices(&usecase->device_list,
2686 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302687 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2688 if (usecase->stream.inout == NULL) {
2689 ALOGE("%s: stream.inout is NULL", __func__);
2690 return -EINVAL;
2691 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302692 struct listnode out_devices;
2693 list_init(&out_devices);
2694 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2695 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002696 assign_devices(&usecase->device_list,
2697 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002698 } else {
2699 /*
2700 * If the voice call is active, use the sound devices of voice call usecase
2701 * so that it would not result any device switch. All the usecases will
2702 * be switched to new device when select_devices() is called for voice call
2703 * usecase. This is to avoid switching devices for voice call when
2704 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002705 * choose voice call device only if the use case device is
2706 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002707 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002708 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002709 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002710 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002711 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2712 is_codec_backend_out_device_type(&usecase->device_list)) ||
2713 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2714 is_codec_backend_in_device_type(&usecase->device_list)) ||
2715 is_single_device_type_equal(&vc_usecase->device_list,
2716 AUDIO_DEVICE_OUT_HEARING_AID) ||
2717 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002718 AUDIO_DEVICE_IN_VOICE_CALL) ||
2719 (is_single_device_type_equal(&usecase->device_list,
2720 AUDIO_DEVICE_IN_USB_HEADSET) &&
2721 is_single_device_type_equal(&vc_usecase->device_list,
2722 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002723 in_snd_device = vc_usecase->in_snd_device;
2724 out_snd_device = vc_usecase->out_snd_device;
2725 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002726 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002727 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002728 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002729 if ((voip_usecase != NULL) &&
2730 (usecase->type == PCM_PLAYBACK) &&
2731 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002732 out_snd_device_backend_match = platform_check_backends_match(
2733 voip_usecase->out_snd_device,
2734 platform_get_output_snd_device(
2735 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302736 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002737 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002738 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2739 (is_codec_backend_out_device_type(&usecase->device_list) ||
2740 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002741 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002742 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002743 in_snd_device = voip_usecase->in_snd_device;
2744 out_snd_device = voip_usecase->out_snd_device;
2745 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002746 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002747 hfp_ucid = audio_extn_hfp_get_usecase();
2748 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002749 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002750 in_snd_device = hfp_usecase->in_snd_device;
2751 out_snd_device = hfp_usecase->out_snd_device;
2752 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002753 }
2754 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302755 if (usecase->stream.out == NULL) {
2756 ALOGE("%s: stream.out is NULL", __func__);
2757 return -EINVAL;
2758 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002759 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002760 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002761 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002762 struct stream_out *voip_out = adev->primary_output;
2763 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002764 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002765 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2766 else
2767 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302768 usecase->stream.out,
2769 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002770 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002771
Eric Laurent637e2d42018-11-15 12:24:31 -08002772 if (voip_usecase)
2773 voip_out = voip_usecase->stream.out;
2774
2775 if (usecase->stream.out == voip_out && voip_in != NULL)
2776 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002777 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002778 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302779 if (usecase->stream.in == NULL) {
2780 ALOGE("%s: stream.in is NULL", __func__);
2781 return -EINVAL;
2782 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002783 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002784 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002785 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002786 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002787 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002788 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002789
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002790 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002791 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002792 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2793 USECASE_AUDIO_PLAYBACK_VOIP);
2794
Carter Hsu2e429db2019-05-14 18:50:52 +08002795 usecase->stream.in->enable_ec_port = false;
2796
Zhou Song62ea0282020-03-22 19:53:01 +08002797 bool is_ha_usecase = adev->ha_proxy_enable ?
2798 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2799 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2800 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002801 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002802 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002803 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002804 } else if (adev->primary_output &&
2805 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002806 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002807 } else {
2808 /* forcing speaker o/p device to get matching i/p pair
2809 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002810 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002811 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002812 priority_in = voip_in;
2813 } else {
2814 /* get the input with the highest priority source*/
2815 priority_in = get_priority_input(adev);
2816
2817 if (!priority_in)
2818 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002819 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002820
Eric Laurent637e2d42018-11-15 12:24:31 -08002821 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002822 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302823 &out_devices,
2824 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002825 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002826 }
2827 }
2828
2829 if (out_snd_device == usecase->out_snd_device &&
2830 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302831
2832 if (!force_device_switch(usecase))
2833 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834 }
2835
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002836 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002837 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002838 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002839 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2840 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302841 }
2842
Aalique Grahame22e49102018-12-18 14:23:57 -08002843 if (out_snd_device != SND_DEVICE_NONE &&
2844 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2845 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2846 __func__,
2847 use_case_table[uc_id],
2848 adev->last_logged_snd_device[uc_id][0],
2849 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2850 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2851 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2852 -1,
2853 out_snd_device,
2854 platform_get_snd_device_name(out_snd_device),
2855 platform_get_snd_device_acdb_id(out_snd_device));
2856 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2857 }
2858 if (in_snd_device != SND_DEVICE_NONE &&
2859 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2860 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2861 __func__,
2862 use_case_table[uc_id],
2863 adev->last_logged_snd_device[uc_id][1],
2864 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2865 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2866 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2867 -1,
2868 in_snd_device,
2869 platform_get_snd_device_name(in_snd_device),
2870 platform_get_snd_device_acdb_id(in_snd_device));
2871 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2872 }
2873
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 /*
2876 * Limitation: While in call, to do a device switch we need to disable
2877 * and enable both RX and TX devices though one of them is same as current
2878 * device.
2879 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002880 if ((usecase->type == VOICE_CALL) &&
2881 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2882 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002883 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002884 }
2885
2886 if (((usecase->type == VOICE_CALL) ||
2887 (usecase->type == VOIP_CALL)) &&
2888 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2889 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302890 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002891 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002892 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002893
2894 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302895 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002896 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002897 }
2898
Aalique Grahame22e49102018-12-18 14:23:57 -08002899 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2900 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002901 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302902 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002903 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2904 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2905 else
2906 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302907 }
2908
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002909 /* Disable current sound devices */
2910 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002911 disable_audio_route(adev, usecase);
2912 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913 }
2914
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002915 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002916 disable_audio_route(adev, usecase);
2917 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918 }
2919
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002920 /* Applicable only on the targets that has external modem.
2921 * New device information should be sent to modem before enabling
2922 * the devices to reduce in-call device switch time.
2923 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002924 if ((usecase->type == VOICE_CALL) &&
2925 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2926 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002927 status = platform_switch_voice_call_enable_device_config(adev->platform,
2928 out_snd_device,
2929 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002930 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002931
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002932 /* Enable new sound devices */
2933 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002934 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302935 if (platform_check_codec_asrc_support(adev->platform))
2936 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002937 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938 }
2939
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002940 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302941 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002942 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002943 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002944
Avinash Vaish71a8b972014-07-24 15:36:33 +05302945 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002946 status = platform_switch_voice_call_device_post(adev->platform,
2947 out_snd_device,
2948 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302949 enable_audio_route_for_voice_usecases(adev, usecase);
2950 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002951
sangwoo170731f2013-06-08 15:36:36 +09002952 usecase->in_snd_device = in_snd_device;
2953 usecase->out_snd_device = out_snd_device;
2954
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302955 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2956 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302957 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002958 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002959 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002960 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2961 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2962 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2963 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2964 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2965 /*
2966 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2967 * configured device sample rate, if not update the COPP rate to be equal to the
2968 * device sample rate, else open COPP at stream sample rate
2969 */
2970 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2971 usecase->stream.out->sample_rate,
2972 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302973 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302974 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2975 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302976 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002977 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2978 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2979 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2980 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002981 }
2982 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002983
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002984 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002985
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002986 /* If input stream is already running then effect needs to be
2987 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002988 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002989 check_and_enable_effect(adev);
2990
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002991 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002992 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302993 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002994 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2995
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002996 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302997 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002998 voice_extn_compress_voip_is_started(adev))
2999 voice_set_sidetone(adev, out_snd_device, true);
3000 }
3001
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003002 /* Applicable only on the targets that has external modem.
3003 * Enable device command should be sent to modem only after
3004 * enabling voice call mixer controls
3005 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003006 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003007 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3008 out_snd_device,
3009 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303010
3011 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003012 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303013 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003014 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303015 if (is_bt_soc_on(adev) == false){
3016 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003017 if (in->pcm != NULL)
3018 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303019 }
3020 }
3021 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3022 && usecase->stream.out->started) {
3023 if (is_bt_soc_on(adev) == false) {
3024 ALOGD("BT SCO/A2DP disconnected while in connection");
3025 out_standby_l(&usecase->stream.out->stream.common);
3026 }
3027 }
3028 } else if ((usecase->stream.out != NULL) &&
3029 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303030 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3031 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003032 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303033 usecase->stream.out->started) {
3034 if (is_bt_soc_on(adev) == false) {
3035 ALOGD("BT SCO/A2dp disconnected while in connection");
3036 out_standby_l(&usecase->stream.out->stream.common);
3037 }
3038 }
3039 }
3040
Yung Ti Su70cb8242018-06-22 17:38:47 +08003041 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003042 struct stream_out *voip_out = voip_usecase->stream.out;
3043 audio_extn_utils_send_app_type_gain(adev,
3044 voip_out->app_type_cfg.app_type,
3045 &voip_out->app_type_cfg.gain[0]);
3046 }
3047
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303048 ALOGD("%s: done",__func__);
3049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 return status;
3051}
3052
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053static int stop_input_stream(struct stream_in *in)
3054{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303055 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303057
3058 if (in == NULL) {
3059 ALOGE("%s: stream_in ptr is NULL", __func__);
3060 return -EINVAL;
3061 }
3062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003064 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065
Eric Laurent994a6932013-07-17 11:51:42 -07003066 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003067 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 uc_info = get_usecase_from_list(adev, in->usecase);
3069 if (uc_info == NULL) {
3070 ALOGE("%s: Could not find the usecase (%d) in the list",
3071 __func__, in->usecase);
3072 return -EINVAL;
3073 }
3074
Carter Hsu2e429db2019-05-14 18:50:52 +08003075 priority_in = get_priority_input(adev);
3076
Derek Chenea197282019-01-07 17:35:01 -08003077 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3078 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003079
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003080 /* Close in-call recording streams */
3081 voice_check_and_stop_incall_rec_usecase(adev, in);
3082
Eric Laurent150dbfe2013-02-27 14:31:02 -08003083 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003084 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003085
3086 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003087 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003089 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303090 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3091
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003092 list_remove(&uc_info->list);
3093 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094
Carter Hsu2e429db2019-05-14 18:50:52 +08003095 if (priority_in == in) {
3096 priority_in = get_priority_input(adev);
3097 if (priority_in)
3098 select_devices(adev, priority_in->usecase);
3099 }
3100
Vatsal Buchac09ae062018-11-14 13:25:08 +05303101 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003102 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103 return ret;
3104}
3105
3106int start_input_stream(struct stream_in *in)
3107{
3108 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003109 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303111
3112 if (in == NULL) {
3113 ALOGE("%s: stream_in ptr is NULL", __func__);
3114 return -EINVAL;
3115 }
3116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003118 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003119 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120
Mingming Yin2664a5b2015-09-03 10:53:11 -07003121 if (get_usecase_from_list(adev, usecase) == NULL)
3122 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303123 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3124 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003125
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303126 if (CARD_STATUS_OFFLINE == in->card_status||
3127 CARD_STATUS_OFFLINE == adev->card_status) {
3128 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303129 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303130 goto error_config;
3131 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303132
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003133 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303134 if (!adev->bt_sco_on) {
3135 ALOGE("%s: SCO profile is not ready, return error", __func__);
3136 ret = -EIO;
3137 goto error_config;
3138 }
3139 }
3140
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003141 /* Check if source matches incall recording usecase criteria */
3142 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3143 if (ret)
3144 goto error_config;
3145 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003146 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3147
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303148 if (audio_extn_cin_attached_usecase(in))
3149 audio_extn_cin_acquire_usecase(in);
3150
Mingming Yin2664a5b2015-09-03 10:53:11 -07003151 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3152 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3153 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003154 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003155 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003156
Eric Laurentb23d5282013-05-14 15:27:20 -07003157 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 if (in->pcm_device_id < 0) {
3159 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3160 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003161 ret = -EINVAL;
3162 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003166
3167 if (!uc_info) {
3168 ret = -ENOMEM;
3169 goto error_config;
3170 }
3171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 uc_info->id = in->usecase;
3173 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003174 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003175 list_init(&uc_info->device_list);
3176 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003177 uc_info->in_snd_device = SND_DEVICE_NONE;
3178 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003180 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003181 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303182 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3183 adev->perf_lock_opts,
3184 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003185 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186
Derek Chenea197282019-01-07 17:35:01 -08003187 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3188 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003189
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303190 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3191
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303192 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303193 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303194 if (ret)
3195 goto error_open;
3196 else
3197 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003198 }
3199
Haynes Mathew George16081042017-05-31 17:16:49 -07003200 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003201 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003202 ALOGE("%s: pcm stream not ready", __func__);
3203 goto error_open;
3204 }
3205 ret = pcm_start(in->pcm);
3206 if (ret < 0) {
3207 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3208 goto error_open;
3209 }
3210 } else {
3211 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3212 unsigned int pcm_open_retry_count = 0;
3213
Zhou Song62ea0282020-03-22 19:53:01 +08003214 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3215 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003216 flags |= PCM_MMAP | PCM_NOIRQ;
3217 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3218 } else if (in->realtime) {
3219 flags |= PCM_MMAP | PCM_NOIRQ;
3220 }
3221
Garmond Leunge2433c32017-09-28 21:51:22 -07003222 if (audio_extn_ffv_get_stream() == in) {
3223 ALOGD("%s: ffv stream, update pcm config", __func__);
3224 audio_extn_ffv_update_pcm_config(&config);
3225 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003226 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3227 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3228
3229 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003230 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003231 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003232 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003233 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303234 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303235 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3236 adev->card_status = CARD_STATUS_OFFLINE;
3237 in->card_status = CARD_STATUS_OFFLINE;
3238 ret = -EIO;
3239 goto error_open;
3240 }
3241
Haynes Mathew George16081042017-05-31 17:16:49 -07003242 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3243 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3244 if (in->pcm != NULL) {
3245 pcm_close(in->pcm);
3246 in->pcm = NULL;
3247 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003248 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003249 ret = -EIO;
3250 goto error_open;
3251 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003252 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003253 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3254 continue;
3255 }
3256 break;
3257 }
3258
3259 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003260 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003261 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003262 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003263 if (ret < 0) {
3264 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3265 pcm_close(in->pcm);
3266 in->pcm = NULL;
3267 goto error_open;
3268 }
3269 register_in_stream(in);
3270 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003271 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003272 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003273 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003274 if (ret < 0) {
3275 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003276 pcm_close(in->pcm);
3277 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003278 goto error_open;
3279 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003280 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003281 }
3282
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003283 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003284 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3285 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003286
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003287 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303288 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3289
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303290done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003291 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303292 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003293 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303294 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003295 return ret;
3296
3297error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003298 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303299 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003301
Eric Laurentc8400632013-02-14 19:04:54 -08003302error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303303 /*
3304 * sleep 50ms to allow sufficient time for kernel
3305 * drivers to recover incases like SSR.
3306 */
3307 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003308 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303309 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003310 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311}
3312
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003313void lock_input_stream(struct stream_in *in)
3314{
3315 pthread_mutex_lock(&in->pre_lock);
3316 pthread_mutex_lock(&in->lock);
3317 pthread_mutex_unlock(&in->pre_lock);
3318}
3319
3320void lock_output_stream(struct stream_out *out)
3321{
3322 pthread_mutex_lock(&out->pre_lock);
3323 pthread_mutex_lock(&out->lock);
3324 pthread_mutex_unlock(&out->pre_lock);
3325}
3326
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003327/* must be called with out->lock locked */
3328static int send_offload_cmd_l(struct stream_out* out, int command)
3329{
3330 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3331
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003332 if (!cmd) {
3333 ALOGE("failed to allocate mem for command 0x%x", command);
3334 return -ENOMEM;
3335 }
3336
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003337 ALOGVV("%s %d", __func__, command);
3338
3339 cmd->cmd = command;
3340 list_add_tail(&out->offload_cmd_list, &cmd->node);
3341 pthread_cond_signal(&out->offload_cond);
3342 return 0;
3343}
3344
3345/* must be called iwth out->lock locked */
3346static void stop_compressed_output_l(struct stream_out *out)
3347{
3348 out->offload_state = OFFLOAD_STATE_IDLE;
3349 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003350 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003351 if (out->compr != NULL) {
3352 compress_stop(out->compr);
3353 while (out->offload_thread_blocked) {
3354 pthread_cond_wait(&out->cond, &out->lock);
3355 }
3356 }
3357}
3358
Varun Balaraje49253e2017-07-06 19:48:56 +05303359bool is_interactive_usecase(audio_usecase_t uc_id)
3360{
3361 unsigned int i;
3362 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3363 if (uc_id == interactive_usecases[i])
3364 return true;
3365 }
3366 return false;
3367}
3368
3369static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3370{
3371 audio_usecase_t ret_uc = USECASE_INVALID;
3372 unsigned int intract_uc_index;
3373 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3374
3375 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3376 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3377 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3378 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3379 ret_uc = interactive_usecases[intract_uc_index];
3380 break;
3381 }
3382 }
3383
3384 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3385 return ret_uc;
3386}
3387
3388static void free_interactive_usecase(struct audio_device *adev,
3389 audio_usecase_t uc_id)
3390{
3391 unsigned int interact_uc_index;
3392 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3393
3394 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3395 if (interactive_usecases[interact_uc_index] == uc_id) {
3396 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3397 break;
3398 }
3399 }
3400 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3401}
3402
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003403bool is_offload_usecase(audio_usecase_t uc_id)
3404{
3405 unsigned int i;
3406 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3407 if (uc_id == offload_usecases[i])
3408 return true;
3409 }
3410 return false;
3411}
3412
Dhananjay Kumarac341582017-02-23 23:42:25 +05303413static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003414{
vivek mehta446c3962015-09-14 10:57:35 -07003415 audio_usecase_t ret_uc = USECASE_INVALID;
3416 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003417 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003418 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303419 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003420 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3421 else
3422 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003423
vivek mehta446c3962015-09-14 10:57:35 -07003424 pthread_mutex_lock(&adev->lock);
3425 if (get_usecase_from_list(adev, ret_uc) != NULL)
3426 ret_uc = USECASE_INVALID;
3427 pthread_mutex_unlock(&adev->lock);
3428
3429 return ret_uc;
3430 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003431
3432 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003433 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3434 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3435 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3436 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003437 break;
3438 }
3439 }
vivek mehta446c3962015-09-14 10:57:35 -07003440
3441 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3442 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003443}
3444
3445static void free_offload_usecase(struct audio_device *adev,
3446 audio_usecase_t uc_id)
3447{
vivek mehta446c3962015-09-14 10:57:35 -07003448 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003449 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003450
3451 if (!adev->multi_offload_enable)
3452 return;
3453
3454 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3455 if (offload_usecases[offload_uc_index] == uc_id) {
3456 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003457 break;
3458 }
3459 }
3460 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3461}
3462
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003463static void *offload_thread_loop(void *context)
3464{
3465 struct stream_out *out = (struct stream_out *) context;
3466 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003467 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003468
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003469 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003470 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003471 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3472
3473 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003474 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003475 out->offload_state = OFFLOAD_STATE_IDLE;
3476 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003477 for (;;) {
3478 struct offload_cmd *cmd = NULL;
3479 stream_callback_event_t event;
3480 bool send_callback = false;
3481
3482 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3483 __func__, list_empty(&out->offload_cmd_list),
3484 out->offload_state);
3485 if (list_empty(&out->offload_cmd_list)) {
3486 ALOGV("%s SLEEPING", __func__);
3487 pthread_cond_wait(&out->offload_cond, &out->lock);
3488 ALOGV("%s RUNNING", __func__);
3489 continue;
3490 }
3491
3492 item = list_head(&out->offload_cmd_list);
3493 cmd = node_to_item(item, struct offload_cmd, node);
3494 list_remove(item);
3495
3496 ALOGVV("%s STATE %d CMD %d out->compr %p",
3497 __func__, out->offload_state, cmd->cmd, out->compr);
3498
3499 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3500 free(cmd);
3501 break;
3502 }
3503
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003504 // allow OFFLOAD_CMD_ERROR reporting during standby
3505 // this is needed to handle failures during compress_open
3506 // Note however that on a pause timeout, the stream is closed
3507 // and no offload usecase will be active. Therefore this
3508 // special case is needed for compress_open failures alone
3509 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3510 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003511 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003512 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003513 pthread_cond_signal(&out->cond);
3514 continue;
3515 }
3516 out->offload_thread_blocked = true;
3517 pthread_mutex_unlock(&out->lock);
3518 send_callback = false;
3519 switch(cmd->cmd) {
3520 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003521 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003522 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003523 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003524 send_callback = true;
3525 event = STREAM_CBK_EVENT_WRITE_READY;
3526 break;
3527 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003528 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303529 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003530 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303531 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003532 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303533 if (ret < 0)
3534 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303535 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303536 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003537 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003538 else
3539 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003540 if (-ENETRESET != ret && !(-EINTR == ret &&
3541 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303542 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303543 pthread_mutex_lock(&out->lock);
3544 out->send_new_metadata = 1;
3545 out->send_next_track_params = true;
3546 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303547 event = STREAM_CBK_EVENT_DRAIN_READY;
3548 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3549 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303550 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003551 break;
3552 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003553 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003554 ret = compress_drain(out->compr);
3555 ALOGD("copl(%p):out of compress_drain", out);
3556 // EINTR check avoids drain interruption due to SSR
3557 if (-ENETRESET != ret && !(-EINTR == ret &&
3558 CARD_STATUS_OFFLINE == out->card_status)) {
3559 send_callback = true;
3560 event = STREAM_CBK_EVENT_DRAIN_READY;
3561 } else
3562 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003563 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303564 case OFFLOAD_CMD_ERROR:
3565 ALOGD("copl(%p): sending error callback to AF", out);
3566 send_callback = true;
3567 event = STREAM_CBK_EVENT_ERROR;
3568 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003569 default:
3570 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3571 break;
3572 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003573 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003574 out->offload_thread_blocked = false;
3575 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003576 if (send_callback && out->client_callback) {
3577 ALOGVV("%s: sending client_callback event %d", __func__, event);
3578 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003579 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003580 free(cmd);
3581 }
3582
3583 pthread_cond_signal(&out->cond);
3584 while (!list_empty(&out->offload_cmd_list)) {
3585 item = list_head(&out->offload_cmd_list);
3586 list_remove(item);
3587 free(node_to_item(item, struct offload_cmd, node));
3588 }
3589 pthread_mutex_unlock(&out->lock);
3590
3591 return NULL;
3592}
3593
3594static int create_offload_callback_thread(struct stream_out *out)
3595{
3596 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3597 list_init(&out->offload_cmd_list);
3598 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3599 offload_thread_loop, out);
3600 return 0;
3601}
3602
3603static int destroy_offload_callback_thread(struct stream_out *out)
3604{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003605 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003606 stop_compressed_output_l(out);
3607 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3608
3609 pthread_mutex_unlock(&out->lock);
3610 pthread_join(out->offload_thread, (void **) NULL);
3611 pthread_cond_destroy(&out->offload_cond);
3612
3613 return 0;
3614}
3615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616static int stop_output_stream(struct stream_out *out)
3617{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303618 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619 struct audio_usecase *uc_info;
3620 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003621 bool has_voip_usecase =
3622 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623
Eric Laurent994a6932013-07-17 11:51:42 -07003624 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003625 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 uc_info = get_usecase_from_list(adev, out->usecase);
3627 if (uc_info == NULL) {
3628 ALOGE("%s: Could not find the usecase (%d) in the list",
3629 __func__, out->usecase);
3630 return -EINVAL;
3631 }
3632
Derek Chenea197282019-01-07 17:35:01 -08003633 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3634 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003635
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003636 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303637 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003638 if (adev->visualizer_stop_output != NULL)
3639 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003640
3641 audio_extn_dts_remove_state_notifier_node(out->usecase);
3642
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003643 if (adev->offload_effects_stop_output != NULL)
3644 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003645 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3646 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3647 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003648 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003649
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003650 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3651 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003652 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003653 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003654
Eric Laurent150dbfe2013-02-27 14:31:02 -08003655 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003656 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003657
3658 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003659 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660
Aalique Grahame22e49102018-12-18 14:23:57 -08003661 audio_extn_extspk_update(adev->extspk);
3662
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003663 if (is_offload_usecase(out->usecase)) {
3664 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3665 adev->dsp_bit_width_enforce_mode,
3666 false);
3667 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003668 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003669 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3670 false);
3671
3672 if (ret != 0)
3673 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3674 /* default service interval was successfully updated,
3675 reopen USB backend with new service interval */
3676 ret = 0;
3677 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003678
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003679 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303680 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003681 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303682 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003683 ALOGV("Disable passthrough , reset mixer to pcm");
3684 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003685#ifdef AUDIO_GKI_ENABLED
3686 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3687 out->compr_config.codec->reserved[0] = 0;
3688#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003689 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003690#endif
Mingming Yin21854652016-04-13 11:54:02 -07003691 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003692 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3693 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003694
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303695 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003696 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303697 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303698
Manish Dewangan21a850a2017-08-14 12:03:55 +05303699 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003700 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3701 if (ret < 0)
3702 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3703 }
3704
juyuchen2d415992018-11-16 14:15:16 +08003705 /* 1) media + voip output routing to handset must route media back to
3706 speaker when voip stops.
3707 2) trigger voip input to reroute when voip output changes to
3708 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003709 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003710 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003711 struct listnode *node;
3712 struct audio_usecase *usecase;
3713 list_for_each(node, &adev->usecase_list) {
3714 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003715 if ((usecase->type == PCM_CAPTURE &&
3716 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3717 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003718 continue;
3719
3720 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3721 __func__, usecase->id, use_case_table[usecase->id],
3722 out->usecase, use_case_table[out->usecase]);
3723 select_devices(adev, usecase->id);
3724 }
3725 }
3726
Garmond Leung5fd0b552018-04-17 11:56:12 -07003727 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003728 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 return ret;
3730}
3731
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003732struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3733 unsigned int flags, unsigned int pcm_open_retry_count,
3734 struct pcm_config *config)
3735{
3736 struct pcm* pcm = NULL;
3737
3738 while (1) {
3739 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3740 if (pcm == NULL || !pcm_is_ready(pcm)) {
3741 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3742 if (pcm != NULL) {
3743 pcm_close(pcm);
3744 pcm = NULL;
3745 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003746 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003747 return NULL;
3748
Weiyin Jiang72197252019-10-09 11:49:32 +08003749 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003750 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3751 continue;
3752 }
3753 break;
3754 }
3755
3756 if (pcm_is_ready(pcm)) {
3757 int ret = pcm_prepare(pcm);
3758 if (ret < 0) {
3759 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3760 pcm_close(pcm);
3761 pcm = NULL;
3762 }
3763 }
3764
3765 return pcm;
3766}
3767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768int start_output_stream(struct stream_out *out)
3769{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 struct audio_usecase *uc_info;
3772 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003773 char mixer_ctl_name[128];
3774 struct mixer_ctl *ctl = NULL;
3775 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303776 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003777 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778
Haynes Mathew George380745d2017-10-04 15:27:45 -07003779 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003780 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3781 ret = -EINVAL;
3782 goto error_config;
3783 }
3784
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003785 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303786 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003787 get_device_types(&out->device_list), is_haptic_usecase);
3788
3789 bool is_speaker_active = compare_device_type(&out->device_list,
3790 AUDIO_DEVICE_OUT_SPEAKER);
3791 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3792 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303793
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303794 if (CARD_STATUS_OFFLINE == out->card_status ||
3795 CARD_STATUS_OFFLINE == adev->card_status) {
3796 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303797 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003798 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303799 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303800
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003801 //Update incall music usecase to reflect correct voice session
3802 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3803 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3804 if (ret != 0) {
3805 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3806 __func__, ret);
3807 goto error_config;
3808 }
3809 }
3810
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003811 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003812 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003813 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303814 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303815 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303816 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3817 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3818 ret = -EAGAIN;
3819 goto error_config;
3820 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303821 }
3822 }
3823 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003824 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303825 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003826 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303827 //combo usecase just by pass a2dp
3828 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003829 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303830 } else {
3831 ALOGE("%s: SCO profile is not ready, return error", __func__);
3832 ret = -EAGAIN;
3833 goto error_config;
3834 }
3835 }
3836 }
3837
Eric Laurentb23d5282013-05-14 15:27:20 -07003838 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839 if (out->pcm_device_id < 0) {
3840 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3841 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003842 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003843 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844 }
3845
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003846 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003847 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3848 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003849 if (adev->haptic_pcm_device_id < 0) {
3850 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3851 __func__, adev->haptic_pcm_device_id, out->usecase);
3852 ret = -EINVAL;
3853 goto error_config;
3854 }
3855 }
3856
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003858
3859 if (!uc_info) {
3860 ret = -ENOMEM;
3861 goto error_config;
3862 }
3863
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003864 uc_info->id = out->usecase;
3865 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003866 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003867 list_init(&uc_info->device_list);
3868 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003869 uc_info->in_snd_device = SND_DEVICE_NONE;
3870 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003871
3872 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003873 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003874 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3875 /* USB backend is not reopened immediately.
3876 This is eventually done as part of select_devices */
3877 }
3878
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003879 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003880
Wei Wangf7ca6c92017-11-21 14:51:20 -08003881 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303882 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3883 adev->perf_lock_opts,
3884 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303885
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003886 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303887 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303888 if (audio_extn_passthru_is_enabled() &&
3889 audio_extn_passthru_is_passthrough_stream(out)) {
3890 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303891 }
3892 }
3893
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003894 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003895 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303896 if (!a2dp_combo) {
3897 check_a2dp_restore_l(adev, out, false);
3898 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003899 struct listnode dev;
3900 list_init(&dev);
3901 assign_devices(&dev, &out->device_list);
3902 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3903 reassign_device_list(&out->device_list,
3904 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003905 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003906 reassign_device_list(&out->device_list,
3907 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303908 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003909 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303910 }
3911 } else {
3912 select_devices(adev, out->usecase);
3913 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003914
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003915 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3916 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003917 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003918 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003919
Derek Chenea197282019-01-07 17:35:01 -08003920 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3921 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003922
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003923 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3924 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003925
3926 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003927 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003928 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3929 ALOGE("%s: pcm stream not ready", __func__);
3930 goto error_open;
3931 }
3932 ret = pcm_start(out->pcm);
3933 if (ret < 0) {
3934 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3935 goto error_open;
3936 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003937 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003938 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003939 unsigned int flags = PCM_OUT;
3940 unsigned int pcm_open_retry_count = 0;
3941 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3942 flags |= PCM_MMAP | PCM_NOIRQ;
3943 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003944 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003945 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003946 } else
3947 flags |= PCM_MONOTONIC;
3948
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003949 if ((adev->vr_audio_mode_enabled) &&
3950 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3951 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3952 "PCM_Dev %d Topology", out->pcm_device_id);
3953 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3954 if (!ctl) {
3955 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3956 __func__, mixer_ctl_name);
3957 } else {
3958 //if success use ULLPP
3959 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3960 __func__, mixer_ctl_name, out->pcm_device_id);
3961 //There is a still a possibility that some sessions
3962 // that request for FAST|RAW when 3D audio is active
3963 //can go through ULLPP. Ideally we expects apps to
3964 //listen to audio focus and stop concurrent playback
3965 //Also, we will look for mode flag (voice_in_communication)
3966 //before enabling the realtime flag.
3967 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3968 }
3969 }
3970
Surendar Karka91fa3682018-07-02 18:12:12 +05303971 if (out->realtime)
3972 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3973 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3974
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003975 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3976 flags, pcm_open_retry_count,
3977 &(out->config));
3978 if (out->pcm == NULL) {
3979 ret = -EIO;
3980 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003981 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003982
3983 if (is_haptic_usecase) {
3984 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3985 adev->haptic_pcm_device_id,
3986 flags, pcm_open_retry_count,
3987 &(adev->haptics_config));
3988 // failure to open haptics pcm shouldnt stop audio,
3989 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003990
3991 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3992 ALOGD("%s: enable haptic audio synchronization", __func__);
3993 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3994 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003995 }
3996
Surendar Karka91fa3682018-07-02 18:12:12 +05303997 if (!out->realtime)
3998 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303999 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004000
Zhou Song2b8f28f2017-09-11 10:51:38 +08004001 // apply volume for voip playback after path is set up
4002 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4003 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304004 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4005 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304006 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4007 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004008 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4009 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304010 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004011 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004012 /*
4013 * set custom channel map if:
4014 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4015 * 2. custom channel map has been set by client
4016 * else default channel map of FC/FR/FL can always be set to DSP
4017 */
4018 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4019 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4020 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004021 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4022 adev->dsp_bit_width_enforce_mode,
4023 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004025 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004026 out->compr = compress_open(adev->snd_card,
4027 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004028 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004029 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304030 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304031 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4032 adev->card_status = CARD_STATUS_OFFLINE;
4033 out->card_status = CARD_STATUS_OFFLINE;
4034 ret = -EIO;
4035 goto error_open;
4036 }
4037
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004038 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004039 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004040 compress_close(out->compr);
4041 out->compr = NULL;
4042 ret = -EIO;
4043 goto error_open;
4044 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304045 /* compress_open sends params of the track, so reset the flag here */
4046 out->is_compr_metadata_avail = false;
4047
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004048 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004049 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004050
Fred Oh3f43e742015-03-04 18:42:34 -08004051 /* Since small bufs uses blocking writes, a write will be blocked
4052 for the default max poll time (20s) in the event of an SSR.
4053 Reduce the poll time to observe and deal with SSR faster.
4054 */
Ashish Jain5106d362016-05-11 19:23:33 +05304055 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004056 compress_set_max_poll_wait(out->compr, 1000);
4057 }
4058
Manish Dewangan69426c82017-01-30 17:35:36 +05304059 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304060 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304061
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004062 audio_extn_dts_create_state_notifier_node(out->usecase);
4063 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4064 popcount(out->channel_mask),
4065 out->playback_started);
4066
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004067#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304068 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004069 audio_extn_dolby_send_ddp_endp_params(adev);
4070#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304071 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4072 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004073 if (adev->visualizer_start_output != NULL)
4074 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4075 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304076 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004077 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004078 }
Derek Chenf13dd492018-11-13 14:53:51 -08004079
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004080 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004081 /* Update cached volume from media to offload/direct stream */
4082 struct listnode *node = NULL;
4083 list_for_each(node, &adev->active_outputs_list) {
4084 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4085 streams_output_ctxt_t,
4086 list);
4087 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4088 out->volume_l = out_ctxt->output->volume_l;
4089 out->volume_r = out_ctxt->output->volume_r;
4090 }
4091 }
4092 out_set_compr_volume(&out->stream,
4093 out->volume_l, out->volume_r);
4094 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004095 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004096
4097 if (ret == 0) {
4098 register_out_stream(out);
4099 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004100 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4101 ALOGE("%s: pcm stream not ready", __func__);
4102 goto error_open;
4103 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004104 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004105 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004106 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004107 if (ret < 0)
4108 goto error_open;
4109 }
4110 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004111 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304112 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004113 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004114
vivek mehtad15d2bf2019-05-17 13:35:10 -07004115 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4116 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4117 audio_low_latency_hint_start();
4118 }
4119
Manish Dewangan21a850a2017-08-14 12:03:55 +05304120 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004121 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004122 if (ret < 0)
4123 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4124 }
4125
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004126 // consider a scenario where on pause lower layers are tear down.
4127 // so on resume, swap mixer control need to be sent only when
4128 // backend is active, hence rather than sending from enable device
4129 // sending it from start of streamtream
4130
4131 platform_set_swap_channels(adev, true);
4132
Haynes Mathew George380745d2017-10-04 15:27:45 -07004133 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304134 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004135 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004136error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004137 if (adev->haptic_pcm) {
4138 pcm_close(adev->haptic_pcm);
4139 adev->haptic_pcm = NULL;
4140 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004141 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304142 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004144error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304145 /*
4146 * sleep 50ms to allow sufficient time for kernel
4147 * drivers to recover incases like SSR.
4148 */
4149 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004150error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004151 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304152 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004153 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004154}
4155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156static int check_input_parameters(uint32_t sample_rate,
4157 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004158 int channel_count,
4159 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004160{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004161 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304163 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4164 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4165 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004166 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004167 !audio_extn_compr_cap_format_supported(format) &&
4168 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004169 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004170
Aalique Grahame22e49102018-12-18 14:23:57 -08004171 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4172 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4173 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4174 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4175 return -EINVAL;
4176 }
4177
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004178 switch (channel_count) {
4179 case 1:
4180 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304181 case 3:
4182 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004183 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004184 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304185 case 10:
4186 case 12:
4187 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004188 break;
4189 default:
4190 ret = -EINVAL;
4191 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004192
4193 switch (sample_rate) {
4194 case 8000:
4195 case 11025:
4196 case 12000:
4197 case 16000:
4198 case 22050:
4199 case 24000:
4200 case 32000:
4201 case 44100:
4202 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004203 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304204 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004205 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304206 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207 break;
4208 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004209 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210 }
4211
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004212 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004213}
4214
Naresh Tanniru04f71882018-06-26 17:46:22 +05304215
4216/** Add a value in a list if not already present.
4217 * @return true if value was successfully inserted or already present,
4218 * false if the list is full and does not contain the value.
4219 */
4220static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4221 for (size_t i = 0; i < list_length; i++) {
4222 if (list[i] == value) return true; // value is already present
4223 if (list[i] == 0) { // no values in this slot
4224 list[i] = value;
4225 return true; // value inserted
4226 }
4227 }
4228 return false; // could not insert value
4229}
4230
4231/** Add channel_mask in supported_channel_masks if not already present.
4232 * @return true if channel_mask was successfully inserted or already present,
4233 * false if supported_channel_masks is full and does not contain channel_mask.
4234 */
4235static void register_channel_mask(audio_channel_mask_t channel_mask,
4236 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4237 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4238 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4239}
4240
4241/** Add format in supported_formats if not already present.
4242 * @return true if format was successfully inserted or already present,
4243 * false if supported_formats is full and does not contain format.
4244 */
4245static void register_format(audio_format_t format,
4246 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4247 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4248 "%s: stream can not declare supporting its format %x", __func__, format);
4249}
4250/** Add sample_rate in supported_sample_rates if not already present.
4251 * @return true if sample_rate was successfully inserted or already present,
4252 * false if supported_sample_rates is full and does not contain sample_rate.
4253 */
4254static void register_sample_rate(uint32_t sample_rate,
4255 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4256 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4257 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4258}
4259
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004260static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4261{
4262 uint32_t high = num1, low = num2, temp = 0;
4263
4264 if (!num1 || !num2)
4265 return 0;
4266
4267 if (num1 < num2) {
4268 high = num2;
4269 low = num1;
4270 }
4271
4272 while (low != 0) {
4273 temp = low;
4274 low = high % low;
4275 high = temp;
4276 }
4277 return (num1 * num2)/high;
4278}
4279
4280static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4281{
4282 uint32_t remainder = 0;
4283
4284 if (!multiplier)
4285 return num;
4286
4287 remainder = num % multiplier;
4288 if (remainder)
4289 num += (multiplier - remainder);
4290
4291 return num;
4292}
4293
Aalique Grahame22e49102018-12-18 14:23:57 -08004294static size_t get_stream_buffer_size(size_t duration_ms,
4295 uint32_t sample_rate,
4296 audio_format_t format,
4297 int channel_count,
4298 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004299{
4300 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004301 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302
Aalique Grahame22e49102018-12-18 14:23:57 -08004303 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004304 if (is_low_latency)
4305 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304306
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004307 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004308 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309
Ralf Herzbd08d632018-09-28 15:50:49 +02004310 /* make sure the size is multiple of 32 bytes and additionally multiple of
4311 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004312 * At 48 kHz mono 16-bit PCM:
4313 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4314 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004315 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004316 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004317 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004318
4319 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320}
4321
Aalique Grahame22e49102018-12-18 14:23:57 -08004322static size_t get_input_buffer_size(uint32_t sample_rate,
4323 audio_format_t format,
4324 int channel_count,
4325 bool is_low_latency)
4326{
4327 /* Don't know if USB HIFI in this context so use true to be conservative */
4328 if (check_input_parameters(sample_rate, format, channel_count,
4329 true /*is_usb_hifi */) != 0)
4330 return 0;
4331
4332 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4333 sample_rate,
4334 format,
4335 channel_count,
4336 is_low_latency);
4337}
4338
Derek Chenf6318be2017-06-12 17:16:24 -04004339size_t get_output_period_size(uint32_t sample_rate,
4340 audio_format_t format,
4341 int channel_count,
4342 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304343{
4344 size_t size = 0;
4345 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4346
4347 if ((duration == 0) || (sample_rate == 0) ||
4348 (bytes_per_sample == 0) || (channel_count == 0)) {
4349 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4350 bytes_per_sample, channel_count);
4351 return -EINVAL;
4352 }
4353
4354 size = (sample_rate *
4355 duration *
4356 bytes_per_sample *
4357 channel_count) / 1000;
4358 /*
4359 * To have same PCM samples for all channels, the buffer size requires to
4360 * be multiple of (number of channels * bytes per sample)
4361 * For writes to succeed, the buffer must be written at address which is multiple of 32
4362 */
4363 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4364
4365 return (size/(channel_count * bytes_per_sample));
4366}
4367
Zhou Song48453a02018-01-10 17:50:59 +08004368static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304369{
4370 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004371 uint64_t written_frames = 0;
4372 uint64_t kernel_frames = 0;
4373 uint64_t dsp_frames = 0;
4374 uint64_t signed_frames = 0;
4375 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304376
4377 /* This adjustment accounts for buffering after app processor.
4378 * It is based on estimated DSP latency per use case, rather than exact.
4379 */
Robert Lee58215542019-07-15 20:55:12 +08004380 pthread_mutex_lock(&adev->lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004381 dsp_frames = platform_render_latency(out->dev, out->usecase) *
4382 out->sample_rate / 1000000LL;
Robert Lee58215542019-07-15 20:55:12 +08004383 pthread_mutex_unlock(&adev->lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304384
Zhou Song48453a02018-01-10 17:50:59 +08004385 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004386 written_frames = out->written /
4387 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4388
Ashish Jain5106d362016-05-11 19:23:33 +05304389 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4390 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4391 * hence only estimate.
4392 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004393 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4394 kernel_frames = kernel_buffer_size /
4395 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304396
Weiyin Jiang4813da12020-05-28 00:37:28 +08004397 if (written_frames >= (kernel_frames + dsp_frames))
4398 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304399
Zhou Song48453a02018-01-10 17:50:59 +08004400 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304401 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004402 if (timestamp != NULL )
4403 *timestamp = out->writeAt;
4404 } else if (timestamp != NULL) {
4405 clock_gettime(CLOCK_MONOTONIC, timestamp);
4406 }
4407 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304408
Weiyin Jiang4813da12020-05-28 00:37:28 +08004409 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4410 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304411
4412 return actual_frames_rendered;
4413}
4414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004415static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4416{
4417 struct stream_out *out = (struct stream_out *)stream;
4418
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004419 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420}
4421
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004422static int out_set_sample_rate(struct audio_stream *stream __unused,
4423 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004424{
4425 return -ENOSYS;
4426}
4427
4428static size_t out_get_buffer_size(const struct audio_stream *stream)
4429{
4430 struct stream_out *out = (struct stream_out *)stream;
4431
Varun Balaraje49253e2017-07-06 19:48:56 +05304432 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304433 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304434 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304435 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4436 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4437 else
4438 return out->compr_config.fragment_size;
4439 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004440 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304441 else if (is_offload_usecase(out->usecase) &&
4442 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304443 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004444
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004445 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004446 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004447}
4448
4449static uint32_t out_get_channels(const struct audio_stream *stream)
4450{
4451 struct stream_out *out = (struct stream_out *)stream;
4452
4453 return out->channel_mask;
4454}
4455
4456static audio_format_t out_get_format(const struct audio_stream *stream)
4457{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004458 struct stream_out *out = (struct stream_out *)stream;
4459
4460 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004461}
4462
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004463static int out_set_format(struct audio_stream *stream __unused,
4464 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004465{
4466 return -ENOSYS;
4467}
4468
4469static int out_standby(struct audio_stream *stream)
4470{
4471 struct stream_out *out = (struct stream_out *)stream;
4472 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004473 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004474
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304475 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4476 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004478 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004479 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004480 if (adev->adm_deregister_stream)
4481 adev->adm_deregister_stream(adev->adm_data, out->handle);
4482
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004483 if (is_offload_usecase(out->usecase))
4484 stop_compressed_output_l(out);
4485
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004486 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004488 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4489 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304490 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004491 pthread_mutex_unlock(&adev->lock);
4492 pthread_mutex_unlock(&out->lock);
4493 ALOGD("VOIP output entered standby");
4494 return 0;
4495 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004496 if (out->pcm) {
4497 pcm_close(out->pcm);
4498 out->pcm = NULL;
4499 }
Meng Wanga09da002020-04-20 12:56:04 +08004500 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4501 if (adev->haptic_pcm) {
4502 pcm_close(adev->haptic_pcm);
4503 adev->haptic_pcm = NULL;
4504 }
4505
4506 if (adev->haptic_buffer != NULL) {
4507 free(adev->haptic_buffer);
4508 adev->haptic_buffer = NULL;
4509 adev->haptic_buffer_size = 0;
4510 }
4511 adev->haptic_pcm_device_id = 0;
4512 }
4513
Haynes Mathew George16081042017-05-31 17:16:49 -07004514 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4515 do_stop = out->playback_started;
4516 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004517
4518 if (out->mmap_shared_memory_fd >= 0) {
4519 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4520 __func__, out->mmap_shared_memory_fd);
4521 close(out->mmap_shared_memory_fd);
4522 out->mmap_shared_memory_fd = -1;
4523 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004524 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004525 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004526 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304527 out->send_next_track_params = false;
4528 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004529 out->gapless_mdata.encoder_delay = 0;
4530 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004531 if (out->compr != NULL) {
4532 compress_close(out->compr);
4533 out->compr = NULL;
4534 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004535 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004536 if (do_stop) {
4537 stop_output_stream(out);
4538 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304539 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004540 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004541 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004542 }
4543 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304544 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004545 return 0;
4546}
4547
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304548static int out_on_error(struct audio_stream *stream)
4549{
4550 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004551 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304552
4553 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004554 // always send CMD_ERROR for offload streams, this
4555 // is needed e.g. when SSR happens within compress_open
4556 // since the stream is active, offload_callback_thread is also active.
4557 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4558 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004559 }
4560 pthread_mutex_unlock(&out->lock);
4561
4562 status = out_standby(&out->stream.common);
4563
4564 lock_output_stream(out);
4565 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004566 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304567 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304568
4569 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4570 ALOGD("Setting previous card status if offline");
4571 out->prev_card_status_offline = true;
4572 }
4573
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304574 pthread_mutex_unlock(&out->lock);
4575
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004576 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304577}
4578
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304579/*
4580 *standby implementation without locks, assumes that the callee already
4581 *has taken adev and out lock.
4582 */
4583int out_standby_l(struct audio_stream *stream)
4584{
4585 struct stream_out *out = (struct stream_out *)stream;
4586 struct audio_device *adev = out->dev;
4587
4588 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4589 stream, out->usecase, use_case_table[out->usecase]);
4590
4591 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004592 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304593 if (adev->adm_deregister_stream)
4594 adev->adm_deregister_stream(adev->adm_data, out->handle);
4595
4596 if (is_offload_usecase(out->usecase))
4597 stop_compressed_output_l(out);
4598
4599 out->standby = true;
4600 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4601 voice_extn_compress_voip_close_output_stream(stream);
4602 out->started = 0;
4603 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004604 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304605 return 0;
4606 } else if (!is_offload_usecase(out->usecase)) {
4607 if (out->pcm) {
4608 pcm_close(out->pcm);
4609 out->pcm = NULL;
4610 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004611 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4612 if (adev->haptic_pcm) {
4613 pcm_close(adev->haptic_pcm);
4614 adev->haptic_pcm = NULL;
4615 }
4616
4617 if (adev->haptic_buffer != NULL) {
4618 free(adev->haptic_buffer);
4619 adev->haptic_buffer = NULL;
4620 adev->haptic_buffer_size = 0;
4621 }
4622 adev->haptic_pcm_device_id = 0;
4623 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304624 } else {
4625 ALOGD("copl(%p):standby", out);
4626 out->send_next_track_params = false;
4627 out->is_compr_metadata_avail = false;
4628 out->gapless_mdata.encoder_delay = 0;
4629 out->gapless_mdata.encoder_padding = 0;
4630 if (out->compr != NULL) {
4631 compress_close(out->compr);
4632 out->compr = NULL;
4633 }
4634 }
4635 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004636 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304637 }
4638 ALOGD("%s: exit", __func__);
4639 return 0;
4640}
4641
Aalique Grahame22e49102018-12-18 14:23:57 -08004642static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004643{
Aalique Grahame22e49102018-12-18 14:23:57 -08004644 struct stream_out *out = (struct stream_out *)stream;
4645
4646 // We try to get the lock for consistency,
4647 // but it isn't necessary for these variables.
4648 // If we're not in standby, we may be blocked on a write.
4649 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4650 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4651 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4652
Andy Hunga1f48fa2019-07-01 18:14:53 -07004653 char buffer[256]; // for statistics formatting
4654 if (!is_offload_usecase(out->usecase)) {
4655 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4656 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4657 }
4658
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004659 if (out->start_latency_ms.n > 0) {
4660 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4661 dprintf(fd, " Start latency ms: %s\n", buffer);
4662 }
4663
Aalique Grahame22e49102018-12-18 14:23:57 -08004664 if (locked) {
4665 pthread_mutex_unlock(&out->lock);
4666 }
4667
4668 // dump error info
4669 (void)error_log_dump(
4670 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004672 return 0;
4673}
4674
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004675static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4676{
4677 int ret = 0;
4678 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004679
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004680 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004681 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004682 return -EINVAL;
4683 }
4684
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304685 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004686
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004687 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4688 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304689 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004690 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004691 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4692 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304693 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004694 }
4695
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004696 ALOGV("%s new encoder delay %u and padding %u", __func__,
4697 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4698
4699 return 0;
4700}
4701
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004702static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4703{
4704 return out == adev->primary_output || out == adev->voice_tx_output;
4705}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004706
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304707// note: this call is safe only if the stream_cb is
4708// removed first in close_output_stream (as is done now).
4709static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4710{
4711 if (!stream || !parms)
4712 return;
4713
4714 struct stream_out *out = (struct stream_out *)stream;
4715 struct audio_device *adev = out->dev;
4716
4717 card_status_t status;
4718 int card;
4719 if (parse_snd_card_status(parms, &card, &status) < 0)
4720 return;
4721
4722 pthread_mutex_lock(&adev->lock);
4723 bool valid_cb = (card == adev->snd_card);
4724 pthread_mutex_unlock(&adev->lock);
4725
4726 if (!valid_cb)
4727 return;
4728
4729 lock_output_stream(out);
4730 if (out->card_status != status)
4731 out->card_status = status;
4732 pthread_mutex_unlock(&out->lock);
4733
4734 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4735 use_case_table[out->usecase],
4736 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4737
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304738 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304739 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304740 if (voice_is_call_state_active(adev) &&
4741 out == adev->primary_output) {
4742 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4743 pthread_mutex_lock(&adev->lock);
4744 voice_stop_call(adev);
4745 adev->mode = AUDIO_MODE_NORMAL;
4746 pthread_mutex_unlock(&adev->lock);
4747 }
4748 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304749 return;
4750}
4751
Kevin Rocardfce19002017-08-07 19:21:36 -07004752static int get_alive_usb_card(struct str_parms* parms) {
4753 int card;
4754 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4755 !audio_extn_usb_alive(card)) {
4756 return card;
4757 }
4758 return -ENODEV;
4759}
4760
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004761int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004762 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004763{
4764 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004765 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004766 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004767 bool bypass_a2dp = false;
4768 bool reconfig = false;
4769 unsigned long service_interval = 0;
4770
4771 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004772 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4773
4774 list_init(&new_devices);
4775 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004776
4777 lock_output_stream(out);
4778 pthread_mutex_lock(&adev->lock);
4779
4780 /*
4781 * When HDMI cable is unplugged the music playback is paused and
4782 * the policy manager sends routing=0. But the audioflinger continues
4783 * to write data until standby time (3sec). As the HDMI core is
4784 * turned off, the write gets blocked.
4785 * Avoid this by routing audio to speaker until standby.
4786 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004787 if (is_single_device_type_equal(&out->device_list,
4788 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004789 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004790 !audio_extn_passthru_is_passthrough_stream(out) &&
4791 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004792 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004793 }
4794 /*
4795 * When A2DP is disconnected the
4796 * music playback is paused and the policy manager sends routing=0
4797 * But the audioflinger continues to write data until standby time
4798 * (3sec). As BT is turned off, the write gets blocked.
4799 * Avoid this by routing audio to speaker until standby.
4800 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004801 if (is_a2dp_out_device_type(&out->device_list) &&
4802 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004803 !audio_extn_a2dp_source_is_ready() &&
4804 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004805 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004806 }
4807 /*
4808 * When USB headset is disconnected the music platback paused
4809 * and the policy manager send routing=0. But if the USB is connected
4810 * back before the standby time, AFE is not closed and opened
4811 * when USB is connected back. So routing to speker will guarantee
4812 * AFE reconfiguration and AFE will be opend once USB is connected again
4813 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004814 if (is_usb_out_device_type(&out->device_list) &&
4815 list_empty(&new_devices) &&
4816 !audio_extn_usb_connected(NULL)) {
4817 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4818 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004819 /* To avoid a2dp to sco overlapping / BT device improper state
4820 * check with BT lib about a2dp streaming support before routing
4821 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004822 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004823 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004824 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4825 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004826 //combo usecase just by pass a2dp
4827 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4828 bypass_a2dp = true;
4829 } else {
4830 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4831 /* update device to a2dp and don't route as BT returned error
4832 * However it is still possible a2dp routing called because
4833 * of current active device disconnection (like wired headset)
4834 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004835 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004836 pthread_mutex_unlock(&adev->lock);
4837 pthread_mutex_unlock(&out->lock);
4838 goto error;
4839 }
4840 }
4841 }
4842
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004843 // Workaround: If routing to an non existing usb device, fail gracefully
4844 // The routing request will otherwise block during 10 second
4845 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004846 if (is_usb_out_device_type(&new_devices)) {
4847 struct str_parms *parms =
4848 str_parms_create_str(get_usb_device_address(&new_devices));
4849 if (!parms)
4850 goto error;
4851 if ((card = get_alive_usb_card(parms)) >= 0) {
4852 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4853 pthread_mutex_unlock(&adev->lock);
4854 pthread_mutex_unlock(&out->lock);
4855 str_parms_destroy(parms);
4856 ret = -ENOSYS;
4857 goto error;
4858 }
4859 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004860 }
4861
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004862 // Workaround: If routing to an non existing hdmi device, fail gracefully
4863 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4864 (platform_get_edid_info_v2(adev->platform,
4865 out->extconn.cs.controller,
4866 out->extconn.cs.stream) != 0)) {
4867 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4868 pthread_mutex_unlock(&adev->lock);
4869 pthread_mutex_unlock(&out->lock);
4870 ret = -ENOSYS;
4871 goto error;
4872 }
4873
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004874 /*
4875 * select_devices() call below switches all the usecases on the same
4876 * backend to the new device. Refer to check_usecases_codec_backend() in
4877 * the select_devices(). But how do we undo this?
4878 *
4879 * For example, music playback is active on headset (deep-buffer usecase)
4880 * and if we go to ringtones and select a ringtone, low-latency usecase
4881 * will be started on headset+speaker. As we can't enable headset+speaker
4882 * and headset devices at the same time, select_devices() switches the music
4883 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4884 * So when the ringtone playback is completed, how do we undo the same?
4885 *
4886 * We are relying on the out_set_parameters() call on deep-buffer output,
4887 * once the ringtone playback is ended.
4888 * NOTE: We should not check if the current devices are same as new devices.
4889 * Because select_devices() must be called to switch back the music
4890 * playback to headset.
4891 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004892 if (!list_empty(&new_devices)) {
4893 bool same_dev = compare_devices(&out->device_list, &new_devices);
4894 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004895
4896 if (output_drives_call(adev, out)) {
4897 if (!voice_is_call_state_active(adev)) {
4898 if (adev->mode == AUDIO_MODE_IN_CALL) {
4899 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004900 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004901 service_interval =
4902 audio_extn_usb_find_service_interval(true, true /*playback*/);
4903 audio_extn_usb_set_service_interval(true /*playback*/,
4904 service_interval,
4905 &reconfig);
4906 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4907 }
4908 ret = voice_start_call(adev);
4909 }
4910 } else {
4911 adev->current_call_output = out;
4912 voice_update_devices_for_all_voice_usecases(adev);
4913 }
4914 }
4915
4916 if (!out->standby) {
4917 if (!same_dev) {
4918 ALOGV("update routing change");
4919 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4920 adev->perf_lock_opts,
4921 adev->perf_lock_opts_size);
4922 if (adev->adm_on_routing_change)
4923 adev->adm_on_routing_change(adev->adm_data,
4924 out->handle);
4925 }
4926 if (!bypass_a2dp) {
4927 select_devices(adev, out->usecase);
4928 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004929 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4930 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004931 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004932 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004933 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004934 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004935 }
4936
4937 if (!same_dev) {
4938 // on device switch force swap, lower functions will make sure
4939 // to check if swap is allowed or not.
4940 platform_set_swap_channels(adev, true);
4941 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4942 }
4943 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4944 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004945 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004946 pthread_mutex_lock(&out->compr_mute_lock);
4947 out->a2dp_compress_mute = false;
4948 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4949 pthread_mutex_unlock(&out->compr_mute_lock);
4950 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4951 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4952 }
4953 }
4954 }
4955
4956 pthread_mutex_unlock(&adev->lock);
4957 pthread_mutex_unlock(&out->lock);
4958
4959 /*handles device and call state changes*/
4960 audio_extn_extspk_update(adev->extspk);
4961
4962error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004963 ALOGV("%s: exit: code(%d)", __func__, ret);
4964 return ret;
4965}
4966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004967static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4968{
4969 struct stream_out *out = (struct stream_out *)stream;
4970 struct audio_device *adev = out->dev;
4971 struct str_parms *parms;
4972 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004973 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004974 int ext_controller = -1;
4975 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004976
sangwoobc677242013-08-08 16:53:43 +09004977 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004978 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004979 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304980 if (!parms)
4981 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004982
4983 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4984 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08004985 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004986 out->extconn.cs.controller = ext_controller;
4987 out->extconn.cs.stream = ext_stream;
4988 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4989 use_case_table[out->usecase], out->extconn.cs.controller,
4990 out->extconn.cs.stream);
4991 }
4992
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004993 if (out == adev->primary_output) {
4994 pthread_mutex_lock(&adev->lock);
4995 audio_extn_set_parameters(adev, parms);
4996 pthread_mutex_unlock(&adev->lock);
4997 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004998 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004999 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005000 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005001
5002 audio_extn_dts_create_state_notifier_node(out->usecase);
5003 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5004 popcount(out->channel_mask),
5005 out->playback_started);
5006
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005007 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005008 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005009
Surendar Karkaf51b5842018-04-26 11:28:38 +05305010 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5011 sizeof(value));
5012 if (err >= 0) {
5013 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5014 audio_extn_send_dual_mono_mixing_coefficients(out);
5015 }
5016
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305017 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5018 if (err >= 0) {
5019 strlcpy(out->profile, value, sizeof(out->profile));
5020 ALOGV("updating stream profile with value '%s'", out->profile);
5021 lock_output_stream(out);
5022 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5023 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005024 &out->device_list, out->flags,
5025 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305026 out->sample_rate, out->bit_width,
5027 out->channel_mask, out->profile,
5028 &out->app_type_cfg);
5029 pthread_mutex_unlock(&out->lock);
5030 }
5031
Alexy Joseph98988832017-01-13 14:56:59 -08005032 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005033 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5034 // and vendor.audio.hal.output.suspend.supported is set to true
5035 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005036 //check suspend parameter only for low latency and if the property
5037 //is enabled
5038 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5039 ALOGI("%s: got suspend_playback %s", __func__, value);
5040 lock_output_stream(out);
5041 if (!strncmp(value, "false", 5)) {
5042 //suspend_playback=false is supposed to set QOS value back to 75%
5043 //the mixer control sent with value Enable will achieve that
5044 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5045 } else if (!strncmp (value, "true", 4)) {
5046 //suspend_playback=true is supposed to remove QOS value
5047 //resetting the mixer control will set the default value
5048 //for the mixer control which is Disable and this removes the QOS vote
5049 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5050 } else {
5051 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5052 " got %s", __func__, value);
5053 ret = -1;
5054 }
5055
5056 if (ret != 0) {
5057 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5058 __func__, out->pm_qos_mixer_path, ret);
5059 }
5060
5061 pthread_mutex_unlock(&out->lock);
5062 }
5063 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005064
Alexy Joseph98988832017-01-13 14:56:59 -08005065 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005066 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305067error:
Eric Laurent994a6932013-07-17 11:51:42 -07005068 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005069 return ret;
5070}
5071
Paul McLeana50b7332018-12-17 08:24:21 -07005072static int in_set_microphone_direction(const struct audio_stream_in *stream,
5073 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005074 struct stream_in *in = (struct stream_in *)stream;
5075
5076 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5077
5078 in->direction = dir;
5079
5080 if (in->standby)
5081 return 0;
5082
5083 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005084}
5085
5086static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005087 struct stream_in *in = (struct stream_in *)stream;
5088
5089 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5090
5091 if (zoom > 1.0 || zoom < -1.0)
5092 return -EINVAL;
5093
5094 in->zoom = zoom;
5095
5096 if (in->standby)
5097 return 0;
5098
5099 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005100}
5101
5102
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005103static bool stream_get_parameter_channels(struct str_parms *query,
5104 struct str_parms *reply,
5105 audio_channel_mask_t *supported_channel_masks) {
5106 int ret = -1;
5107 char value[512];
5108 bool first = true;
5109 size_t i, j;
5110
5111 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5112 ret = 0;
5113 value[0] = '\0';
5114 i = 0;
5115 while (supported_channel_masks[i] != 0) {
5116 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5117 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5118 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305119 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005120
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305121 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005122 first = false;
5123 break;
5124 }
5125 }
5126 i++;
5127 }
5128 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5129 }
5130 return ret == 0;
5131}
5132
5133static bool stream_get_parameter_formats(struct str_parms *query,
5134 struct str_parms *reply,
5135 audio_format_t *supported_formats) {
5136 int ret = -1;
5137 char value[256];
5138 size_t i, j;
5139 bool first = true;
5140
5141 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5142 ret = 0;
5143 value[0] = '\0';
5144 i = 0;
5145 while (supported_formats[i] != 0) {
5146 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5147 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5148 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305149 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005150 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305151 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005152 first = false;
5153 break;
5154 }
5155 }
5156 i++;
5157 }
5158 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5159 }
5160 return ret == 0;
5161}
5162
5163static bool stream_get_parameter_rates(struct str_parms *query,
5164 struct str_parms *reply,
5165 uint32_t *supported_sample_rates) {
5166
5167 int i;
5168 char value[256];
5169 int ret = -1;
5170 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5171 ret = 0;
5172 value[0] = '\0';
5173 i=0;
5174 int cursor = 0;
5175 while (supported_sample_rates[i]) {
5176 int avail = sizeof(value) - cursor;
5177 ret = snprintf(value + cursor, avail, "%s%d",
5178 cursor > 0 ? "|" : "",
5179 supported_sample_rates[i]);
5180 if (ret < 0 || ret >= avail) {
5181 // if cursor is at the last element of the array
5182 // overwrite with \0 is duplicate work as
5183 // snprintf already put a \0 in place.
5184 // else
5185 // we had space to write the '|' at value[cursor]
5186 // (which will be overwritten) or no space to fill
5187 // the first element (=> cursor == 0)
5188 value[cursor] = '\0';
5189 break;
5190 }
5191 cursor += ret;
5192 ++i;
5193 }
5194 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5195 value);
5196 }
5197 return ret >= 0;
5198}
5199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005200static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5201{
5202 struct stream_out *out = (struct stream_out *)stream;
5203 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005204 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005205 char value[256];
5206 struct str_parms *reply = str_parms_create();
5207 size_t i, j;
5208 int ret;
5209 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005210
5211 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005212 if (reply) {
5213 str_parms_destroy(reply);
5214 }
5215 if (query) {
5216 str_parms_destroy(query);
5217 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005218 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5219 return NULL;
5220 }
5221
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005222 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005223 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5224 if (ret >= 0) {
5225 value[0] = '\0';
5226 i = 0;
5227 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005228 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5229 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005230 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005231 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005232 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005233 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005234 first = false;
5235 break;
5236 }
5237 }
5238 i++;
5239 }
5240 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5241 str = str_parms_to_str(reply);
5242 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005243 voice_extn_out_get_parameters(out, query, reply);
5244 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005245 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005246
Alexy Joseph62142aa2015-11-16 15:10:34 -08005247
5248 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5249 if (ret >= 0) {
5250 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305251 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5252 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005253 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305254 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005255 } else {
5256 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305257 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005258 }
5259 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005260 if (str)
5261 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005262 str = str_parms_to_str(reply);
5263 }
5264
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005265 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5266 if (ret >= 0) {
5267 value[0] = '\0';
5268 i = 0;
5269 first = true;
5270 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005271 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5272 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005273 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005274 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005275 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005276 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005277 first = false;
5278 break;
5279 }
5280 }
5281 i++;
5282 }
5283 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005284 if (str)
5285 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005286 str = str_parms_to_str(reply);
5287 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005288
5289 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5290 if (ret >= 0) {
5291 value[0] = '\0';
5292 i = 0;
5293 first = true;
5294 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005295 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5296 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005297 if (!first) {
5298 strlcat(value, "|", sizeof(value));
5299 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005300 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005301 first = false;
5302 break;
5303 }
5304 }
5305 i++;
5306 }
5307 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5308 if (str)
5309 free(str);
5310 str = str_parms_to_str(reply);
5311 }
5312
Alexy Joseph98988832017-01-13 14:56:59 -08005313 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5314 //only low latency track supports suspend_resume
5315 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005316 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005317 if (str)
5318 free(str);
5319 str = str_parms_to_str(reply);
5320 }
5321
5322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005323 str_parms_destroy(query);
5324 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005325 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005326 return str;
5327}
5328
5329static uint32_t out_get_latency(const struct audio_stream_out *stream)
5330{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005331 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005332 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005333 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005334
Alexy Josephaa54c872014-12-03 02:46:47 -08005335 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305336 lock_output_stream(out);
5337 latency = audio_extn_utils_compress_get_dsp_latency(out);
5338 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005339 } else if ((out->realtime) ||
5340 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005341 // since the buffer won't be filled up faster than realtime,
5342 // return a smaller number
5343 if (out->config.rate)
5344 period_ms = (out->af_period_multiplier * out->config.period_size *
5345 1000) / (out->config.rate);
5346 else
5347 period_ms = 0;
Robert Lee58215542019-07-15 20:55:12 +08005348 pthread_mutex_lock(&adev->lock);
5349 latency = period_ms + platform_render_latency(out->dev, out->usecase)/1000;
5350 pthread_mutex_unlock(&adev->lock);
Alexy Josephaa54c872014-12-03 02:46:47 -08005351 } else {
5352 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005353 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005354 }
5355
Zhou Songd2537a02020-06-11 22:04:46 +08005356 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005357 latency += audio_extn_a2dp_get_encoder_latency();
5358
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305359 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005360 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005361}
5362
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305363static float AmpToDb(float amplification)
5364{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305365 float db = DSD_VOLUME_MIN_DB;
5366 if (amplification > 0) {
5367 db = 20 * log10(amplification);
5368 if(db < DSD_VOLUME_MIN_DB)
5369 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305370 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305371 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305372}
5373
Arun Mirpuri5d170872019-03-26 13:21:31 -07005374static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5375 float right)
5376{
5377 struct stream_out *out = (struct stream_out *)stream;
5378 long volume = 0;
5379 char mixer_ctl_name[128] = "";
5380 struct audio_device *adev = out->dev;
5381 struct mixer_ctl *ctl = NULL;
5382 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5383 PCM_PLAYBACK);
5384
5385 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5386 "Playback %d Volume", pcm_device_id);
5387 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5388 if (!ctl) {
5389 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5390 __func__, mixer_ctl_name);
5391 return -EINVAL;
5392 }
5393 if (left != right)
5394 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5395 __func__, left, right);
5396 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5397 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5398 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5399 __func__, mixer_ctl_name, volume);
5400 return -EINVAL;
5401 }
5402 return 0;
5403}
5404
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305405static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5406 float right)
5407{
5408 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305409 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305410 char mixer_ctl_name[128];
5411 struct audio_device *adev = out->dev;
5412 struct mixer_ctl *ctl;
5413 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5414 PCM_PLAYBACK);
5415
5416 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5417 "Compress Playback %d Volume", pcm_device_id);
5418 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5419 if (!ctl) {
5420 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5421 __func__, mixer_ctl_name);
5422 return -EINVAL;
5423 }
5424 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5425 __func__, mixer_ctl_name, left, right);
5426 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5427 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5428 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5429
5430 return 0;
5431}
5432
Zhou Song2b8f28f2017-09-11 10:51:38 +08005433static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5434 float right)
5435{
5436 struct stream_out *out = (struct stream_out *)stream;
5437 char mixer_ctl_name[] = "App Type Gain";
5438 struct audio_device *adev = out->dev;
5439 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305440 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005441
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005442 if (!is_valid_volume(left, right)) {
5443 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5444 __func__, left, right);
5445 return -EINVAL;
5446 }
5447
Zhou Song2b8f28f2017-09-11 10:51:38 +08005448 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5449 if (!ctl) {
5450 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5451 __func__, mixer_ctl_name);
5452 return -EINVAL;
5453 }
5454
5455 set_values[0] = 0; //0: Rx Session 1:Tx Session
5456 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305457 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5458 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005459
5460 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5461 return 0;
5462}
5463
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305464static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5465 float right)
5466{
5467 struct stream_out *out = (struct stream_out *)stream;
5468 /* Volume control for pcm playback */
5469 if (left != right) {
5470 return -EINVAL;
5471 } else {
5472 char mixer_ctl_name[128];
5473 struct audio_device *adev = out->dev;
5474 struct mixer_ctl *ctl;
5475 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5476 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5477 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5478 if (!ctl) {
5479 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5480 return -EINVAL;
5481 }
5482
5483 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5484 int ret = mixer_ctl_set_value(ctl, 0, volume);
5485 if (ret < 0) {
5486 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5487 return -EINVAL;
5488 }
5489
5490 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5491
5492 return 0;
5493 }
5494}
5495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005496static int out_set_volume(struct audio_stream_out *stream, float left,
5497 float right)
5498{
Eric Laurenta9024de2013-04-04 09:19:12 -07005499 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005500 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305501 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005502
Arun Mirpuri5d170872019-03-26 13:21:31 -07005503 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005504 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5505 /* only take left channel into account: the API is for stereo anyway */
5506 out->muted = (left == 0.0f);
5507 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005508 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305509 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005510 /*
5511 * Set mute or umute on HDMI passthrough stream.
5512 * Only take left channel into account.
5513 * Mute is 0 and unmute 1
5514 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305515 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305516 } else if (out->format == AUDIO_FORMAT_DSD){
5517 char mixer_ctl_name[128] = "DSD Volume";
5518 struct audio_device *adev = out->dev;
5519 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5520
5521 if (!ctl) {
5522 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5523 __func__, mixer_ctl_name);
5524 return -EINVAL;
5525 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305526 volume[0] = (long)(AmpToDb(left));
5527 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305528 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5529 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005530 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005531 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005532 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5533 struct listnode *node = NULL;
5534 list_for_each(node, &adev->active_outputs_list) {
5535 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5536 streams_output_ctxt_t,
5537 list);
5538 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5539 out->volume_l = out_ctxt->output->volume_l;
5540 out->volume_r = out_ctxt->output->volume_r;
5541 }
5542 }
5543 if (!out->a2dp_compress_mute) {
5544 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5545 }
5546 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005547 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305548 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005549 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305550 if (!out->a2dp_compress_mute)
5551 ret = out_set_compr_volume(stream, left, right);
5552 out->volume_l = left;
5553 out->volume_r = right;
5554 pthread_mutex_unlock(&out->compr_mute_lock);
5555 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005556 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005557 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005558 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5559 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5560 if (!out->standby) {
5561 audio_extn_utils_send_app_type_gain(out->dev,
5562 out->app_type_cfg.app_type,
5563 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005564 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005565 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005566 out->volume_l = left;
5567 out->volume_r = right;
5568 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005569 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5570 ALOGV("%s: MMAP set volume called", __func__);
5571 if (!out->standby)
5572 ret = out_set_mmap_volume(stream, left, right);
5573 out->volume_l = left;
5574 out->volume_r = right;
5575 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305576 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305577 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5578 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305579 /* Volume control for pcm playback */
5580 if (!out->standby)
5581 ret = out_set_pcm_volume(stream, left, right);
5582 else
5583 out->apply_volume = true;
5584
5585 out->volume_l = left;
5586 out->volume_r = right;
5587 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005588 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5589 ALOGV("%s: bus device set volume called", __func__);
5590 if (!out->standby)
5591 ret = out_set_pcm_volume(stream, left, right);
5592 out->volume_l = left;
5593 out->volume_r = right;
5594 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005595 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005597 return -ENOSYS;
5598}
5599
Zhou Songc9672822017-08-16 16:01:39 +08005600static void update_frames_written(struct stream_out *out, size_t bytes)
5601{
5602 size_t bpf = 0;
5603
5604 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5605 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5606 bpf = 1;
5607 else if (!is_offload_usecase(out->usecase))
5608 bpf = audio_bytes_per_sample(out->format) *
5609 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005610
5611 pthread_mutex_lock(&out->position_query_lock);
5612 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005613 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005614 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5615 }
5616 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005617}
5618
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005619int split_and_write_audio_haptic_data(struct stream_out *out,
5620 const void *buffer, size_t bytes_to_write)
5621{
5622 struct audio_device *adev = out->dev;
5623
5624 int ret = 0;
5625 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5626 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5627 size_t frame_size = channel_count * bytes_per_sample;
5628 size_t frame_count = bytes_to_write / frame_size;
5629
5630 bool force_haptic_path =
5631 property_get_bool("vendor.audio.test_haptic", false);
5632
5633 // extract Haptics data from Audio buffer
5634 bool alloc_haptic_buffer = false;
5635 int haptic_channel_count = adev->haptics_config.channels;
5636 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5637 size_t audio_frame_size = frame_size - haptic_frame_size;
5638 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5639
5640 if (adev->haptic_buffer == NULL) {
5641 alloc_haptic_buffer = true;
5642 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5643 free(adev->haptic_buffer);
5644 adev->haptic_buffer_size = 0;
5645 alloc_haptic_buffer = true;
5646 }
5647
5648 if (alloc_haptic_buffer) {
5649 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005650 if(adev->haptic_buffer == NULL) {
5651 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5652 return -ENOMEM;
5653 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005654 adev->haptic_buffer_size = total_haptic_buffer_size;
5655 }
5656
5657 size_t src_index = 0, aud_index = 0, hap_index = 0;
5658 uint8_t *audio_buffer = (uint8_t *)buffer;
5659 uint8_t *haptic_buffer = adev->haptic_buffer;
5660
5661 // This is required for testing only. This works for stereo data only.
5662 // One channel is fed to audio stream and other to haptic stream for testing.
5663 if (force_haptic_path)
5664 audio_frame_size = haptic_frame_size = bytes_per_sample;
5665
5666 for (size_t i = 0; i < frame_count; i++) {
5667 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5668 audio_frame_size);
5669 aud_index += audio_frame_size;
5670 src_index += audio_frame_size;
5671
5672 if (adev->haptic_pcm)
5673 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5674 haptic_frame_size);
5675 hap_index += haptic_frame_size;
5676 src_index += haptic_frame_size;
5677
5678 // This is required for testing only.
5679 // Discard haptic channel data.
5680 if (force_haptic_path)
5681 src_index += haptic_frame_size;
5682 }
5683
5684 // write to audio pipeline
5685 ret = pcm_write(out->pcm, (void *)audio_buffer,
5686 frame_count * audio_frame_size);
5687
5688 // write to haptics pipeline
5689 if (adev->haptic_pcm)
5690 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5691 frame_count * haptic_frame_size);
5692
5693 return ret;
5694}
5695
Aalique Grahame22e49102018-12-18 14:23:57 -08005696#ifdef NO_AUDIO_OUT
5697static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5698 const void *buffer __unused, size_t bytes)
5699{
5700 struct stream_out *out = (struct stream_out *)stream;
5701
5702 /* No Output device supported other than BT for playback.
5703 * Sleep for the amount of buffer duration
5704 */
5705 lock_output_stream(out);
5706 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5707 (const struct audio_stream_out *)&out->stream) /
5708 out_get_sample_rate(&out->stream.common));
5709 pthread_mutex_unlock(&out->lock);
5710 return bytes;
5711}
5712#endif
5713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005714static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5715 size_t bytes)
5716{
5717 struct stream_out *out = (struct stream_out *)stream;
5718 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005719 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305720 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005721 const size_t frame_size = audio_stream_out_frame_size(stream);
5722 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305723 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005724 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005725
Haynes Mathew George380745d2017-10-04 15:27:45 -07005726 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005727 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305728
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305729 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005730
Dhananjay Kumarac341582017-02-23 23:42:25 +05305731 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305732 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305733 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5734 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005735 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305736 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305737 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305738 ALOGD(" %s: sound card is not active/SSR state", __func__);
5739 ret= -EIO;
5740 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305741 }
5742 }
5743
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305744 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305745 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305746 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305747 goto exit;
5748 }
5749
Haynes Mathew George16081042017-05-31 17:16:49 -07005750 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5751 ret = -EINVAL;
5752 goto exit;
5753 }
5754
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005755 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305756 !out->is_iec61937_info_available) {
5757
5758 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5759 out->is_iec61937_info_available = true;
5760 } else if (audio_extn_passthru_is_enabled()) {
5761 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305762 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305763
5764 if((out->format == AUDIO_FORMAT_DTS) ||
5765 (out->format == AUDIO_FORMAT_DTS_HD)) {
5766 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5767 buffer, bytes);
5768 if (ret) {
5769 if (ret != -ENOSYS) {
5770 out->is_iec61937_info_available = false;
5771 ALOGD("iec61937 transmission info not yet updated retry");
5772 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305773 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305774 /* if stream has started and after that there is
5775 * stream config change (iec transmission config)
5776 * then trigger select_device to update backend configuration.
5777 */
5778 out->stream_config_changed = true;
5779 pthread_mutex_lock(&adev->lock);
5780 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305781 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005782 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305783 ret = -EINVAL;
5784 goto exit;
5785 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305786 pthread_mutex_unlock(&adev->lock);
5787 out->stream_config_changed = false;
5788 out->is_iec61937_info_available = true;
5789 }
5790 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305791
Meng Wang4c32fb42020-01-16 17:57:11 +08005792#ifdef AUDIO_GKI_ENABLED
5793 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5794 compr_passthr = out->compr_config.codec->reserved[0];
5795#else
5796 compr_passthr = out->compr_config.codec->compr_passthr;
5797#endif
5798
Garmond Leung317cbf12017-09-13 16:20:50 -07005799 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005800 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305801 (out->is_iec61937_info_available == true)) {
5802 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5803 ret = -EINVAL;
5804 goto exit;
5805 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305806 }
5807 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305808
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005809 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005810 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005811 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5812 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305813 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305814 ret = -EIO;
5815 goto exit;
5816 }
5817 }
5818 }
5819
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005820 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005821 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005822 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5823
Eric Laurent150dbfe2013-02-27 14:31:02 -08005824 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005825 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5826 ret = voice_extn_compress_voip_start_output_stream(out);
5827 else
5828 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005829 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005830 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005831 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005832 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005833 goto exit;
5834 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305835 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005836 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
vivek mehtab72d08d2016-04-29 03:16:47 -07005837 if (last_known_cal_step != -1) {
5838 ALOGD("%s: retry previous failed cal level set", __func__);
5839 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305840 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005841 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305842
5843 if ((out->is_iec61937_info_available == true) &&
5844 (audio_extn_passthru_is_passthrough_stream(out))&&
5845 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5846 ret = -EINVAL;
5847 goto exit;
5848 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305849 if (out->set_dual_mono)
5850 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005851
5852 // log startup time in ms.
5853 simple_stats_log(
5854 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005855 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005856
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005857 if (adev->is_channel_status_set == false &&
5858 compare_device_type(&out->device_list,
5859 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005860 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305861 adev->is_channel_status_set = true;
5862 }
5863
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305864 if ((adev->use_old_pspd_mix_ctrl == true) &&
5865 (out->pspd_coeff_sent == false)) {
5866 /*
5867 * Need to resend pspd coefficients after stream started for
5868 * older kernel version as it does not save the coefficients
5869 * and also stream has to be started for coeff to apply.
5870 */
5871 usecase = get_usecase_from_list(adev, out->usecase);
5872 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305873 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305874 out->pspd_coeff_sent = true;
5875 }
5876 }
5877
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005878 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005879 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005880 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005881 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005882 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5883 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305884 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5885 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005886 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305887 out->send_next_track_params = false;
5888 out->is_compr_metadata_avail = false;
5889 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005890 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305891 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305892 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005893
Ashish Jain83a6cc22016-06-28 14:34:17 +05305894 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305895 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305896 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305897 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005898 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305899 return -EINVAL;
5900 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305901 audio_format_t dst_format = out->hal_op_format;
5902 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305903
Dieter Luecking5d57def2018-09-07 14:23:37 +02005904 /* prevent division-by-zero */
5905 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5906 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5907 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5908 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305909 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005910 ATRACE_END();
5911 return -EINVAL;
5912 }
5913
Ashish Jainf1eaa582016-05-23 20:54:24 +05305914 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5915 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5916
Ashish Jain83a6cc22016-06-28 14:34:17 +05305917 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305918 dst_format,
5919 buffer,
5920 src_format,
5921 frames);
5922
Ashish Jain83a6cc22016-06-28 14:34:17 +05305923 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305924 bytes_to_write);
5925
5926 /*Convert written bytes in audio flinger format*/
5927 if (ret > 0)
5928 ret = ((ret * format_to_bitwidth_table[out->format]) /
5929 format_to_bitwidth_table[dst_format]);
5930 }
5931 } else
5932 ret = compress_write(out->compr, buffer, bytes);
5933
Zhou Songc9672822017-08-16 16:01:39 +08005934 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5935 update_frames_written(out, bytes);
5936
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305937 if (ret < 0)
5938 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005939 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305940 /*msg to cb thread only if non blocking write is enabled*/
5941 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305942 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005943 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305944 } else if (-ENETRESET == ret) {
5945 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305946 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305947 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305948 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005949 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305950 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005951 }
Ashish Jain5106d362016-05-11 19:23:33 +05305952
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305953 /* Call compr start only when non-zero bytes of data is there to be rendered */
5954 if (!out->playback_started && ret > 0) {
5955 int status = compress_start(out->compr);
5956 if (status < 0) {
5957 ret = status;
5958 ALOGE("%s: compr start failed with err %d", __func__, errno);
5959 goto exit;
5960 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005961 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005962 out->playback_started = 1;
5963 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005964
5965 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5966 popcount(out->channel_mask),
5967 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005968 }
5969 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005970 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005971 return ret;
5972 } else {
5973 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005974 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005975 if (out->muted)
5976 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005977 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5978 __func__, frames, frame_size, bytes_to_write);
5979
Aalique Grahame22e49102018-12-18 14:23:57 -08005980 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005981 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5982 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5983 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005984 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5985 int16_t *src = (int16_t *)buffer;
5986 int16_t *dst = (int16_t *)buffer;
5987
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005988 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005989 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005990 "out_write called for %s use case with wrong properties",
5991 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005992
5993 /*
5994 * FIXME: this can be removed once audio flinger mixer supports
5995 * mono output
5996 */
5997
5998 /*
5999 * Code below goes over each frame in the buffer and adds both
6000 * L and R samples and then divides by 2 to convert to mono
6001 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006002 if (channel_count == 2) {
6003 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6004 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6005 }
6006 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006007 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006008 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006009
6010 // Note: since out_get_presentation_position() is called alternating with out_write()
6011 // by AudioFlinger, we can check underruns using the prior timestamp read.
6012 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6013 if (out->last_fifo_valid) {
6014 // compute drain to see if there is an underrun.
6015 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
6016 const int64_t frames_by_time =
6017 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
6018 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6019
6020 if (underrun > 0) {
6021 simple_stats_log(&out->fifo_underruns, underrun);
6022
6023 ALOGW("%s: underrun(%lld) "
6024 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6025 __func__,
6026 (long long)out->fifo_underruns.n,
6027 (long long)frames_by_time,
6028 (long long)out->last_fifo_frames_remaining);
6029 }
6030 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6031 }
6032
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306033 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006034
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006035 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006036
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006037 if (out->config.rate)
6038 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6039 out->config.rate;
6040
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006041 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006042 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6043
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006044 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006045 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006046 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306047 out->convert_buffer != NULL) {
6048
6049 memcpy_by_audio_format(out->convert_buffer,
6050 out->hal_op_format,
6051 buffer,
6052 out->hal_ip_format,
6053 out->config.period_size * out->config.channels);
6054
6055 ret = pcm_write(out->pcm, out->convert_buffer,
6056 (out->config.period_size *
6057 out->config.channels *
6058 format_to_bitwidth_table[out->hal_op_format]));
6059 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306060 /*
6061 * To avoid underrun in DSP when the application is not pumping
6062 * data at required rate, check for the no. of bytes and ignore
6063 * pcm_write if it is less than actual buffer size.
6064 * It is a work around to a change in compress VOIP driver.
6065 */
6066 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6067 bytes < (out->config.period_size * out->config.channels *
6068 audio_bytes_per_sample(out->format))) {
6069 size_t voip_buf_size =
6070 out->config.period_size * out->config.channels *
6071 audio_bytes_per_sample(out->format);
6072 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6073 __func__, bytes, voip_buf_size);
6074 usleep(((uint64_t)voip_buf_size - bytes) *
6075 1000000 / audio_stream_out_frame_size(stream) /
6076 out_get_sample_rate(&out->stream.common));
6077 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006078 } else {
6079 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6080 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6081 else
6082 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6083 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306084 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006085
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006086 release_out_focus(out);
6087
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306088 if (ret < 0)
6089 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006090 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306091 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006092 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006093 }
6094
6095exit:
Zhou Songc9672822017-08-16 16:01:39 +08006096 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306097 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306098 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306099 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006100 pthread_mutex_unlock(&out->lock);
6101
6102 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006103 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006104 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306105 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306106 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306107 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306108 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306109 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306110 out->standby = true;
6111 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306112 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006113 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6114 /* prevent division-by-zero */
6115 uint32_t stream_size = audio_stream_out_frame_size(stream);
6116 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006117
Dieter Luecking5d57def2018-09-07 14:23:37 +02006118 if ((stream_size == 0) || (srate == 0)) {
6119 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6120 ATRACE_END();
6121 return -EINVAL;
6122 }
6123 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6124 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006125 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306126 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006127 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006128 return ret;
6129 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006130 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006131 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006132 return bytes;
6133}
6134
6135static int out_get_render_position(const struct audio_stream_out *stream,
6136 uint32_t *dsp_frames)
6137{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006138 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006139
6140 if (dsp_frames == NULL)
6141 return -EINVAL;
6142
6143 *dsp_frames = 0;
6144 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006145 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306146
6147 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6148 * this operation and adev_close_output_stream(where out gets reset).
6149 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306150 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006151 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306152 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006153 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306154 return 0;
6155 }
6156
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006157 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306158 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306159 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006160 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306161 if (ret < 0)
6162 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006163 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306164 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006165 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306166 if (-ENETRESET == ret) {
6167 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306168 out->card_status = CARD_STATUS_OFFLINE;
6169 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306170 } else if(ret < 0) {
6171 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306172 ret = -EINVAL;
6173 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306174 /*
6175 * Handle corner case where compress session is closed during SSR
6176 * and timestamp is queried
6177 */
6178 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306179 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306180 } else if (out->prev_card_status_offline) {
6181 ALOGE("ERROR: previously sound card was offline,return error");
6182 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306183 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306184 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006185 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306186 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306187 pthread_mutex_unlock(&out->lock);
6188 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006189 } else if (audio_is_linear_pcm(out->format)) {
6190 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006191 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006192 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006193 } else
6194 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006195}
6196
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006197static int out_add_audio_effect(const struct audio_stream *stream __unused,
6198 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006199{
6200 return 0;
6201}
6202
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006203static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6204 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006205{
6206 return 0;
6207}
6208
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006209static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6210 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006211{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306212 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006213}
6214
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006215static int out_get_presentation_position(const struct audio_stream_out *stream,
6216 uint64_t *frames, struct timespec *timestamp)
6217{
6218 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306219 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006220 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006221
Ashish Jain5106d362016-05-11 19:23:33 +05306222 /* below piece of code is not guarded against any lock because audioFliner serializes
6223 * this operation and adev_close_output_stream( where out gets reset).
6224 */
6225 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306226 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006227 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306228 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6229 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6230 return 0;
6231 }
6232
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006233 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006234
Ashish Jain5106d362016-05-11 19:23:33 +05306235 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6236 ret = compress_get_tstamp(out->compr, &dsp_frames,
6237 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006238 // Adjustment accounts for A2dp encoder latency with offload usecases
6239 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006240 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006241 unsigned long offset =
6242 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6243 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6244 }
Ashish Jain5106d362016-05-11 19:23:33 +05306245 ALOGVV("%s rendered frames %ld sample_rate %d",
6246 __func__, dsp_frames, out->sample_rate);
6247 *frames = dsp_frames;
6248 if (ret < 0)
6249 ret = -errno;
6250 if (-ENETRESET == ret) {
6251 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306252 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306253 ret = -EINVAL;
6254 } else
6255 ret = 0;
6256 /* this is the best we can do */
6257 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006258 } else {
6259 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006260 unsigned int avail;
6261 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006262 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006263 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006264
Andy Hunga1f48fa2019-07-01 18:14:53 -07006265 if (out->kernel_buffer_size > avail) {
6266 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6267 } else {
6268 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6269 __func__, avail, out->kernel_buffer_size);
6270 avail = out->kernel_buffer_size;
6271 frames_temp = out->last_fifo_frames_remaining = 0;
6272 }
6273 out->last_fifo_valid = true;
6274 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6275
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006276 if (out->written >= frames_temp)
6277 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006278
Andy Hunga1f48fa2019-07-01 18:14:53 -07006279 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6280 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6281
Weiyin Jiangd4633762018-03-16 12:05:03 +08006282 // This adjustment accounts for buffering after app processor.
6283 // It is based on estimated DSP latency per use case, rather than exact.
Robert Lee58215542019-07-15 20:55:12 +08006284 pthread_mutex_lock(&adev->lock);
6285 frames_temp = platform_render_latency(out->dev, out->usecase) *
6286 out->sample_rate / 1000000LL;
6287 pthread_mutex_unlock(&adev->lock);
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006288 if (signed_frames >= frames_temp)
6289 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006290
Weiyin Jiangd4633762018-03-16 12:05:03 +08006291 // Adjustment accounts for A2dp encoder latency with non offload usecases
6292 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006293 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006294 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6295 if (signed_frames >= frames_temp)
6296 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006297 }
6298
6299 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006300 *frames = signed_frames;
6301 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006302 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006303 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6304 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006305 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306306 *frames = out->written;
6307 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306308 if (is_offload_usecase(out->usecase))
6309 ret = -EINVAL;
6310 else
6311 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006312 }
6313 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006314 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006315 return ret;
6316}
6317
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006318static int out_set_callback(struct audio_stream_out *stream,
6319 stream_callback_t callback, void *cookie)
6320{
6321 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006322 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006323
6324 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006325 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006326 out->client_callback = callback;
6327 out->client_cookie = cookie;
6328 if (out->adsp_hdlr_stream_handle) {
6329 ret = audio_extn_adsp_hdlr_stream_set_callback(
6330 out->adsp_hdlr_stream_handle,
6331 callback,
6332 cookie);
6333 if (ret)
6334 ALOGW("%s:adsp hdlr callback registration failed %d",
6335 __func__, ret);
6336 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006337 pthread_mutex_unlock(&out->lock);
6338 return 0;
6339}
6340
6341static int out_pause(struct audio_stream_out* stream)
6342{
6343 struct stream_out *out = (struct stream_out *)stream;
6344 int status = -ENOSYS;
6345 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006346 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006347 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306348 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006349 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006350 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306351 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306352 status = compress_pause(out->compr);
6353
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006354 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006355
Mingming Yin21854652016-04-13 11:54:02 -07006356 if (audio_extn_passthru_is_active()) {
6357 ALOGV("offload use case, pause passthru");
6358 audio_extn_passthru_on_pause(out);
6359 }
6360
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306361 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006362 audio_extn_dts_notify_playback_state(out->usecase, 0,
6363 out->sample_rate, popcount(out->channel_mask),
6364 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006365 }
6366 pthread_mutex_unlock(&out->lock);
6367 }
6368 return status;
6369}
6370
6371static int out_resume(struct audio_stream_out* stream)
6372{
6373 struct stream_out *out = (struct stream_out *)stream;
6374 int status = -ENOSYS;
6375 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006376 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006377 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306378 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006379 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006380 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306381 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306382 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006383 }
6384 if (!status) {
6385 out->offload_state = OFFLOAD_STATE_PLAYING;
6386 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306387 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006388 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6389 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006390 }
6391 pthread_mutex_unlock(&out->lock);
6392 }
6393 return status;
6394}
6395
6396static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6397{
6398 struct stream_out *out = (struct stream_out *)stream;
6399 int status = -ENOSYS;
6400 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006401 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006402 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006403 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6404 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6405 else
6406 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6407 pthread_mutex_unlock(&out->lock);
6408 }
6409 return status;
6410}
6411
6412static int out_flush(struct audio_stream_out* stream)
6413{
6414 struct stream_out *out = (struct stream_out *)stream;
6415 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006416 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006417 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006418 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006419 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6420 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006421 } else {
6422 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6423 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006424 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006425 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006426 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006427 return 0;
6428 }
6429 return -ENOSYS;
6430}
6431
Haynes Mathew George16081042017-05-31 17:16:49 -07006432static int out_stop(const struct audio_stream_out* stream)
6433{
6434 struct stream_out *out = (struct stream_out *)stream;
6435 struct audio_device *adev = out->dev;
6436 int ret = -ENOSYS;
6437
6438 ALOGV("%s", __func__);
6439 pthread_mutex_lock(&adev->lock);
6440 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6441 out->playback_started && out->pcm != NULL) {
6442 pcm_stop(out->pcm);
6443 ret = stop_output_stream(out);
6444 out->playback_started = false;
6445 }
6446 pthread_mutex_unlock(&adev->lock);
6447 return ret;
6448}
6449
6450static int out_start(const struct audio_stream_out* stream)
6451{
6452 struct stream_out *out = (struct stream_out *)stream;
6453 struct audio_device *adev = out->dev;
6454 int ret = -ENOSYS;
6455
6456 ALOGV("%s", __func__);
6457 pthread_mutex_lock(&adev->lock);
6458 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6459 !out->playback_started && out->pcm != NULL) {
6460 ret = start_output_stream(out);
6461 if (ret == 0) {
6462 out->playback_started = true;
6463 }
6464 }
6465 pthread_mutex_unlock(&adev->lock);
6466 return ret;
6467}
6468
6469/*
6470 * Modify config->period_count based on min_size_frames
6471 */
6472static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6473{
6474 int periodCountRequested = (min_size_frames + config->period_size - 1)
6475 / config->period_size;
6476 int periodCount = MMAP_PERIOD_COUNT_MIN;
6477
6478 ALOGV("%s original config.period_size = %d config.period_count = %d",
6479 __func__, config->period_size, config->period_count);
6480
6481 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6482 periodCount *= 2;
6483 }
6484 config->period_count = periodCount;
6485
6486 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6487}
6488
Phil Burkfe17efd2019-03-25 10:23:35 -07006489// Read offset for the positional timestamp from a persistent vendor property.
6490// This is to workaround apparent inaccuracies in the timing information that
6491// is used by the AAudio timing model. The inaccuracies can cause glitches.
6492static int64_t get_mmap_out_time_offset() {
6493 const int32_t kDefaultOffsetMicros = 0;
6494 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006495 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006496 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6497 return mmap_time_offset_micros * (int64_t)1000;
6498}
6499
Haynes Mathew George16081042017-05-31 17:16:49 -07006500static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6501 int32_t min_size_frames,
6502 struct audio_mmap_buffer_info *info)
6503{
6504 struct stream_out *out = (struct stream_out *)stream;
6505 struct audio_device *adev = out->dev;
6506 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006507 unsigned int offset1 = 0;
6508 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006509 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006510 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006511 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006512
Arun Mirpuri5d170872019-03-26 13:21:31 -07006513 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306514 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006515 pthread_mutex_lock(&adev->lock);
6516
Sharad Sanglec6f32552018-05-04 16:15:38 +05306517 if (CARD_STATUS_OFFLINE == out->card_status ||
6518 CARD_STATUS_OFFLINE == adev->card_status) {
6519 ALOGW("out->card_status or adev->card_status offline, try again");
6520 ret = -EIO;
6521 goto exit;
6522 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306523 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006524 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6525 ret = -EINVAL;
6526 goto exit;
6527 }
6528 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6529 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6530 ret = -ENOSYS;
6531 goto exit;
6532 }
6533 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6534 if (out->pcm_device_id < 0) {
6535 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6536 __func__, out->pcm_device_id, out->usecase);
6537 ret = -EINVAL;
6538 goto exit;
6539 }
6540
6541 adjust_mmap_period_count(&out->config, min_size_frames);
6542
Arun Mirpuri5d170872019-03-26 13:21:31 -07006543 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006544 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6545 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6546 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306547 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306548 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6549 out->card_status = CARD_STATUS_OFFLINE;
6550 adev->card_status = CARD_STATUS_OFFLINE;
6551 ret = -EIO;
6552 goto exit;
6553 }
6554
Haynes Mathew George16081042017-05-31 17:16:49 -07006555 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6556 step = "open";
6557 ret = -ENODEV;
6558 goto exit;
6559 }
6560 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6561 if (ret < 0) {
6562 step = "begin";
6563 goto exit;
6564 }
juyuchen626833d2019-06-04 16:48:02 +08006565
6566 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006567 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006568 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006569 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006570 ret = platform_get_mmap_data_fd(adev->platform,
6571 out->pcm_device_id, 0 /*playback*/,
6572 &info->shared_memory_fd,
6573 &mmap_size);
6574 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006575 // Fall back to non exclusive mode
6576 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6577 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006578 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6579 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6580
Arun Mirpuri5d170872019-03-26 13:21:31 -07006581 if (mmap_size < buffer_size) {
6582 step = "mmap";
6583 goto exit;
6584 }
juyuchen626833d2019-06-04 16:48:02 +08006585 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006586 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006587 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006588 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006589
6590 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6591 if (ret < 0) {
6592 step = "commit";
6593 goto exit;
6594 }
6595
Phil Burkfe17efd2019-03-25 10:23:35 -07006596 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6597
Haynes Mathew George16081042017-05-31 17:16:49 -07006598 out->standby = false;
6599 ret = 0;
6600
Arun Mirpuri5d170872019-03-26 13:21:31 -07006601 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006602 __func__, info->shared_memory_address, info->buffer_size_frames);
6603
6604exit:
6605 if (ret != 0) {
6606 if (out->pcm == NULL) {
6607 ALOGE("%s: %s - %d", __func__, step, ret);
6608 } else {
6609 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6610 pcm_close(out->pcm);
6611 out->pcm = NULL;
6612 }
6613 }
6614 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306615 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006616 return ret;
6617}
6618
6619static int out_get_mmap_position(const struct audio_stream_out *stream,
6620 struct audio_mmap_position *position)
6621{
6622 struct stream_out *out = (struct stream_out *)stream;
6623 ALOGVV("%s", __func__);
6624 if (position == NULL) {
6625 return -EINVAL;
6626 }
6627 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006628 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006629 return -ENOSYS;
6630 }
6631 if (out->pcm == NULL) {
6632 return -ENOSYS;
6633 }
6634
6635 struct timespec ts = { 0, 0 };
6636 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6637 if (ret < 0) {
6638 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6639 return ret;
6640 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006641 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6642 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006643 return 0;
6644}
6645
6646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006647/** audio_stream_in implementation **/
6648static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6649{
6650 struct stream_in *in = (struct stream_in *)stream;
6651
6652 return in->config.rate;
6653}
6654
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006655static int in_set_sample_rate(struct audio_stream *stream __unused,
6656 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006657{
6658 return -ENOSYS;
6659}
6660
6661static size_t in_get_buffer_size(const struct audio_stream *stream)
6662{
6663 struct stream_in *in = (struct stream_in *)stream;
6664
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006665 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6666 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006667 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6668 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306669 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306670 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006671
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006672 return in->config.period_size * in->af_period_multiplier *
6673 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006674}
6675
6676static uint32_t in_get_channels(const struct audio_stream *stream)
6677{
6678 struct stream_in *in = (struct stream_in *)stream;
6679
6680 return in->channel_mask;
6681}
6682
6683static audio_format_t in_get_format(const struct audio_stream *stream)
6684{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006685 struct stream_in *in = (struct stream_in *)stream;
6686
6687 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006688}
6689
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006690static int in_set_format(struct audio_stream *stream __unused,
6691 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006692{
6693 return -ENOSYS;
6694}
6695
6696static int in_standby(struct audio_stream *stream)
6697{
6698 struct stream_in *in = (struct stream_in *)stream;
6699 struct audio_device *adev = in->dev;
6700 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306701 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6702 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006703 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306704
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006705 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006706 if (!in->standby && in->is_st_session) {
6707 ALOGD("%s: sound trigger pcm stop lab", __func__);
6708 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006709 if (adev->num_va_sessions > 0)
6710 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006711 in->standby = 1;
6712 }
6713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006714 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006715 if (adev->adm_deregister_stream)
6716 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6717
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006718 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006719 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006720 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006721 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006722 voice_extn_compress_voip_close_input_stream(stream);
6723 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006724 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6725 do_stop = in->capture_started;
6726 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006727 if (in->mmap_shared_memory_fd >= 0) {
6728 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6729 __func__, in->mmap_shared_memory_fd);
6730 close(in->mmap_shared_memory_fd);
6731 in->mmap_shared_memory_fd = -1;
6732 }
Zhou Songa8895042016-07-05 17:54:22 +08006733 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306734 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306735 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006736 }
6737
Arun Mirpuri5d170872019-03-26 13:21:31 -07006738 if (in->pcm) {
6739 ATRACE_BEGIN("pcm_in_close");
6740 pcm_close(in->pcm);
6741 ATRACE_END();
6742 in->pcm = NULL;
6743 }
6744
Carter Hsu2e429db2019-05-14 18:50:52 +08006745 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006746 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006747
George Gao3018ede2019-10-23 13:23:00 -07006748 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6749 if (adev->num_va_sessions > 0)
6750 adev->num_va_sessions--;
6751 }
Quinn Malef6050362019-01-30 15:55:40 -08006752
Eric Laurent150dbfe2013-02-27 14:31:02 -08006753 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006754 }
6755 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006756 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006757 return status;
6758}
6759
Aalique Grahame22e49102018-12-18 14:23:57 -08006760static int in_dump(const struct audio_stream *stream,
6761 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006762{
Aalique Grahame22e49102018-12-18 14:23:57 -08006763 struct stream_in *in = (struct stream_in *)stream;
6764
6765 // We try to get the lock for consistency,
6766 // but it isn't necessary for these variables.
6767 // If we're not in standby, we may be blocked on a read.
6768 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6769 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6770 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6771 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6772
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006773 char buffer[256]; // for statistics formatting
6774 if (in->start_latency_ms.n > 0) {
6775 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6776 dprintf(fd, " Start latency ms: %s\n", buffer);
6777 }
6778
Aalique Grahame22e49102018-12-18 14:23:57 -08006779 if (locked) {
6780 pthread_mutex_unlock(&in->lock);
6781 }
6782
6783 // dump error info
6784 (void)error_log_dump(
6785 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6786
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006787 return 0;
6788}
6789
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306790static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6791{
6792 if (!stream || !parms)
6793 return;
6794
6795 struct stream_in *in = (struct stream_in *)stream;
6796 struct audio_device *adev = in->dev;
6797
6798 card_status_t status;
6799 int card;
6800 if (parse_snd_card_status(parms, &card, &status) < 0)
6801 return;
6802
6803 pthread_mutex_lock(&adev->lock);
6804 bool valid_cb = (card == adev->snd_card);
6805 pthread_mutex_unlock(&adev->lock);
6806
6807 if (!valid_cb)
6808 return;
6809
6810 lock_input_stream(in);
6811 if (in->card_status != status)
6812 in->card_status = status;
6813 pthread_mutex_unlock(&in->lock);
6814
6815 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6816 use_case_table[in->usecase],
6817 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6818
6819 // a better solution would be to report error back to AF and let
6820 // it put the stream to standby
6821 if (status == CARD_STATUS_OFFLINE)
6822 in_standby(&in->stream.common);
6823
6824 return;
6825}
6826
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006827int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006828 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006829 audio_source_t source)
6830{
6831 struct audio_device *adev = in->dev;
6832 int ret = 0;
6833
6834 lock_input_stream(in);
6835 pthread_mutex_lock(&adev->lock);
6836
6837 /* no audio source uses val == 0 */
6838 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6839 in->source = source;
6840 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6841 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6842 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6843 (in->config.rate == 8000 || in->config.rate == 16000 ||
6844 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6845 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6846 ret = voice_extn_compress_voip_open_input_stream(in);
6847 if (ret != 0) {
6848 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6849 __func__, ret);
6850 }
6851 }
6852 }
6853
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006854 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6855 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006856 // Workaround: If routing to an non existing usb device, fail gracefully
6857 // The routing request will otherwise block during 10 second
6858 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006859 struct str_parms *usb_addr =
6860 str_parms_create_str(get_usb_device_address(devices));
6861 if (is_usb_in_device_type(devices) && usb_addr &&
6862 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006863 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6864 ret = -ENOSYS;
6865 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006866 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006867 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006868 if (!in->standby && !in->is_st_session) {
6869 ALOGV("update input routing change");
6870 // inform adm before actual routing to prevent glitches.
6871 if (adev->adm_on_routing_change) {
6872 adev->adm_on_routing_change(adev->adm_data,
6873 in->capture_handle);
6874 ret = select_devices(adev, in->usecase);
6875 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6876 adev->adm_routing_changed = true;
6877 }
6878 }
6879 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006880 if (usb_addr)
6881 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006882 }
6883 pthread_mutex_unlock(&adev->lock);
6884 pthread_mutex_unlock(&in->lock);
6885
6886 ALOGD("%s: exit: status(%d)", __func__, ret);
6887 return ret;
6888}
6889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006890static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6891{
6892 struct stream_in *in = (struct stream_in *)stream;
6893 struct audio_device *adev = in->dev;
6894 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006895 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306896 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006897
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306898 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006899 parms = str_parms_create_str(kvpairs);
6900
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306901 if (!parms)
6902 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006903 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006904 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006905
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306906 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6907 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306908 strlcpy(in->profile, value, sizeof(in->profile));
6909 ALOGV("updating stream profile with value '%s'", in->profile);
6910 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6911 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006912 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306913 in->sample_rate, in->bit_width,
6914 in->profile, &in->app_type_cfg);
6915 }
6916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006917 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006918 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006919
6920 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306921error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306922 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006923}
6924
6925static char* in_get_parameters(const struct audio_stream *stream,
6926 const char *keys)
6927{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006928 struct stream_in *in = (struct stream_in *)stream;
6929 struct str_parms *query = str_parms_create_str(keys);
6930 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006931 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006932
6933 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006934 if (reply) {
6935 str_parms_destroy(reply);
6936 }
6937 if (query) {
6938 str_parms_destroy(query);
6939 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006940 ALOGE("in_get_parameters: failed to create query or reply");
6941 return NULL;
6942 }
6943
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006944 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006945
6946 voice_extn_in_get_parameters(in, query, reply);
6947
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006948 stream_get_parameter_channels(query, reply,
6949 &in->supported_channel_masks[0]);
6950 stream_get_parameter_formats(query, reply,
6951 &in->supported_formats[0]);
6952 stream_get_parameter_rates(query, reply,
6953 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006954 str = str_parms_to_str(reply);
6955 str_parms_destroy(query);
6956 str_parms_destroy(reply);
6957
6958 ALOGV("%s: exit: returns - %s", __func__, str);
6959 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006960}
6961
Aalique Grahame22e49102018-12-18 14:23:57 -08006962static int in_set_gain(struct audio_stream_in *stream,
6963 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006964{
Aalique Grahame22e49102018-12-18 14:23:57 -08006965 struct stream_in *in = (struct stream_in *)stream;
6966 char mixer_ctl_name[128];
6967 struct mixer_ctl *ctl;
6968 int ctl_value;
6969
6970 ALOGV("%s: gain %f", __func__, gain);
6971
6972 if (stream == NULL)
6973 return -EINVAL;
6974
6975 /* in_set_gain() only used to silence MMAP capture for now */
6976 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6977 return -ENOSYS;
6978
6979 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6980
6981 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6982 if (!ctl) {
6983 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6984 __func__, mixer_ctl_name);
6985 return -ENOSYS;
6986 }
6987
6988 if (gain < RECORD_GAIN_MIN)
6989 gain = RECORD_GAIN_MIN;
6990 else if (gain > RECORD_GAIN_MAX)
6991 gain = RECORD_GAIN_MAX;
6992 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6993
6994 mixer_ctl_set_value(ctl, 0, ctl_value);
6995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006996 return 0;
6997}
6998
6999static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7000 size_t bytes)
7001{
7002 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307003
7004 if (in == NULL) {
7005 ALOGE("%s: stream_in ptr is NULL", __func__);
7006 return -EINVAL;
7007 }
7008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007009 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307010 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307011 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007012
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007013 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307014
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007015 if (in->is_st_session) {
7016 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7017 /* Read from sound trigger HAL */
7018 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007019 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007020 if (adev->num_va_sessions < UINT_MAX)
7021 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007022 in->standby = 0;
7023 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007024 pthread_mutex_unlock(&in->lock);
7025 return bytes;
7026 }
7027
Haynes Mathew George16081042017-05-31 17:16:49 -07007028 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7029 ret = -ENOSYS;
7030 goto exit;
7031 }
7032
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007033 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7034 !in->standby && adev->adm_routing_changed) {
7035 ret = -ENOSYS;
7036 goto exit;
7037 }
7038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007039 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007040 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7041
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007042 pthread_mutex_lock(&adev->lock);
7043 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7044 ret = voice_extn_compress_voip_start_input_stream(in);
7045 else
7046 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007047 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7048 if (adev->num_va_sessions < UINT_MAX)
7049 adev->num_va_sessions++;
7050 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007051 pthread_mutex_unlock(&adev->lock);
7052 if (ret != 0) {
7053 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007054 }
7055 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007056
7057 // log startup time in ms.
7058 simple_stats_log(
7059 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007060 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007061
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307062 /* Avoid read if capture_stopped is set */
7063 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7064 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7065 ret = -EINVAL;
7066 goto exit;
7067 }
7068
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007069 // what's the duration requested by the client?
7070 long ns = 0;
7071
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307072 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007073 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7074 in->config.rate;
7075
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007076 ret = request_in_focus(in, ns);
7077 if (ret != 0)
7078 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007079 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007080
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307081 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307082 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7083 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307084 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007085 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307086 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007087 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007088 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007089 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007090 } else if (audio_extn_ffv_get_stream() == in) {
7091 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307092 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007093 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307094 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7095 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7096 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7097 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307098 ret = -EINVAL;
7099 goto exit;
7100 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307101 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307102 ret = -errno;
7103 }
7104 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307105 /* bytes read is always set to bytes for non compress usecases */
7106 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007107 }
7108
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007109 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007111 /*
Quinn Malef6050362019-01-30 15:55:40 -08007112 * Instead of writing zeroes here, we could trust the hardware to always
7113 * provide zeroes when muted. This is also muted with voice recognition
7114 * usecases so that other clients do not have access to voice recognition
7115 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007116 */
Quinn Malef6050362019-01-30 15:55:40 -08007117 if ((ret == 0 && voice_get_mic_mute(adev) &&
7118 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007119 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7120 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007121 (adev->num_va_sessions &&
7122 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7123 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7124 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007125 memset(buffer, 0, bytes);
7126
7127exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307128 frame_size = audio_stream_in_frame_size(stream);
7129 if (frame_size > 0)
7130 in->frames_read += bytes_read/frame_size;
7131
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007132 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307133 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007134 pthread_mutex_unlock(&in->lock);
7135
7136 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307137 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307138 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307139 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307140 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307141 in->standby = true;
7142 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307143 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307144 bytes_read = bytes;
7145 memset(buffer, 0, bytes);
7146 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007147 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007148 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7149 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007150 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307151 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307152 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007153 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307154 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007155}
7156
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007157static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007158{
7159 return 0;
7160}
7161
Aalique Grahame22e49102018-12-18 14:23:57 -08007162static int in_get_capture_position(const struct audio_stream_in *stream,
7163 int64_t *frames, int64_t *time)
7164{
7165 if (stream == NULL || frames == NULL || time == NULL) {
7166 return -EINVAL;
7167 }
7168 struct stream_in *in = (struct stream_in *)stream;
7169 int ret = -ENOSYS;
7170
7171 lock_input_stream(in);
7172 // note: ST sessions do not close the alsa pcm driver synchronously
7173 // on standby. Therefore, we may return an error even though the
7174 // pcm stream is still opened.
7175 if (in->standby) {
7176 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7177 "%s stream in standby but pcm not NULL for non ST session", __func__);
7178 goto exit;
7179 }
7180 if (in->pcm) {
7181 struct timespec timestamp;
7182 unsigned int avail;
7183 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7184 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007185 pthread_mutex_lock(&adev->lock);
7186 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
7187 - platform_capture_latency(in->dev, in->usecase) * 1000LL;
7188 pthread_mutex_unlock(&adev->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08007189 ret = 0;
7190 }
7191 }
7192exit:
7193 pthread_mutex_unlock(&in->lock);
7194 return ret;
7195}
7196
Carter Hsu2e429db2019-05-14 18:50:52 +08007197static int in_update_effect_list(bool add, effect_handle_t effect,
7198 struct listnode *head)
7199{
7200 struct listnode *node;
7201 struct in_effect_list *elist = NULL;
7202 struct in_effect_list *target = NULL;
7203 int ret = 0;
7204
7205 if (!head)
7206 return ret;
7207
7208 list_for_each(node, head) {
7209 elist = node_to_item(node, struct in_effect_list, list);
7210 if (elist->handle == effect) {
7211 target = elist;
7212 break;
7213 }
7214 }
7215
7216 if (add) {
7217 if (target) {
7218 ALOGD("effect %p already exist", effect);
7219 return ret;
7220 }
7221
7222 target = (struct in_effect_list *)
7223 calloc(1, sizeof(struct in_effect_list));
7224
7225 if (!target) {
7226 ALOGE("%s:fail to allocate memory", __func__);
7227 return -ENOMEM;
7228 }
7229
7230 target->handle = effect;
7231 list_add_tail(head, &target->list);
7232 } else {
7233 if (target) {
7234 list_remove(&target->list);
7235 free(target);
7236 }
7237 }
7238
7239 return ret;
7240}
7241
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007242static int add_remove_audio_effect(const struct audio_stream *stream,
7243 effect_handle_t effect,
7244 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007245{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007246 struct stream_in *in = (struct stream_in *)stream;
7247 int status = 0;
7248 effect_descriptor_t desc;
7249
7250 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007251 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7252
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007253 if (status != 0)
7254 return status;
7255
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007256 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007257 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007258 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007259 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7260 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007261 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007262
7263 in_update_effect_list(enable, effect, &in->aec_list);
7264 enable = !list_empty(&in->aec_list);
7265 if (enable == in->enable_aec)
7266 goto exit;
7267
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007268 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007269 ALOGD("AEC enable %d", enable);
7270
Aalique Grahame22e49102018-12-18 14:23:57 -08007271 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7272 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7273 in->dev->enable_voicerx = enable;
7274 struct audio_usecase *usecase;
7275 struct listnode *node;
7276 list_for_each(node, &in->dev->usecase_list) {
7277 usecase = node_to_item(node, struct audio_usecase, list);
7278 if (usecase->type == PCM_PLAYBACK)
7279 select_devices(in->dev, usecase->id);
7280 }
7281 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007282 if (!in->standby) {
7283 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7284 select_devices(in->dev, in->usecase);
7285 }
7286
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007287 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007288 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7289
7290 in_update_effect_list(enable, effect, &in->ns_list);
7291 enable = !list_empty(&in->ns_list);
7292 if (enable == in->enable_ns)
7293 goto exit;
7294
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007295 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007296 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007297 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007298 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7299 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007300 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7301 select_devices(in->dev, in->usecase);
7302 } else
7303 select_devices(in->dev, in->usecase);
7304 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007305 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007306exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007307 pthread_mutex_unlock(&in->dev->lock);
7308 pthread_mutex_unlock(&in->lock);
7309
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007310 return 0;
7311}
7312
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007313static int in_add_audio_effect(const struct audio_stream *stream,
7314 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007315{
Eric Laurent994a6932013-07-17 11:51:42 -07007316 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007317 return add_remove_audio_effect(stream, effect, true);
7318}
7319
7320static int in_remove_audio_effect(const struct audio_stream *stream,
7321 effect_handle_t effect)
7322{
Eric Laurent994a6932013-07-17 11:51:42 -07007323 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007324 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007325}
7326
Derek Chenf939fb72018-11-13 13:34:41 -08007327streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7328 audio_io_handle_t input)
7329{
7330 struct listnode *node;
7331
7332 list_for_each(node, &dev->active_inputs_list) {
7333 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7334 streams_input_ctxt_t,
7335 list);
7336 if (in_ctxt->input->capture_handle == input) {
7337 return in_ctxt;
7338 }
7339 }
7340 return NULL;
7341}
7342
7343streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7344 audio_io_handle_t output)
7345{
7346 struct listnode *node;
7347
7348 list_for_each(node, &dev->active_outputs_list) {
7349 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7350 streams_output_ctxt_t,
7351 list);
7352 if (out_ctxt->output->handle == output) {
7353 return out_ctxt;
7354 }
7355 }
7356 return NULL;
7357}
7358
Haynes Mathew George16081042017-05-31 17:16:49 -07007359static int in_stop(const struct audio_stream_in* stream)
7360{
7361 struct stream_in *in = (struct stream_in *)stream;
7362 struct audio_device *adev = in->dev;
7363
7364 int ret = -ENOSYS;
7365 ALOGV("%s", __func__);
7366 pthread_mutex_lock(&adev->lock);
7367 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7368 in->capture_started && in->pcm != NULL) {
7369 pcm_stop(in->pcm);
7370 ret = stop_input_stream(in);
7371 in->capture_started = false;
7372 }
7373 pthread_mutex_unlock(&adev->lock);
7374 return ret;
7375}
7376
7377static int in_start(const struct audio_stream_in* stream)
7378{
7379 struct stream_in *in = (struct stream_in *)stream;
7380 struct audio_device *adev = in->dev;
7381 int ret = -ENOSYS;
7382
7383 ALOGV("%s in %p", __func__, in);
7384 pthread_mutex_lock(&adev->lock);
7385 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7386 !in->capture_started && in->pcm != NULL) {
7387 if (!in->capture_started) {
7388 ret = start_input_stream(in);
7389 if (ret == 0) {
7390 in->capture_started = true;
7391 }
7392 }
7393 }
7394 pthread_mutex_unlock(&adev->lock);
7395 return ret;
7396}
7397
Phil Burke0a86d12019-02-16 22:28:11 -08007398// Read offset for the positional timestamp from a persistent vendor property.
7399// This is to workaround apparent inaccuracies in the timing information that
7400// is used by the AAudio timing model. The inaccuracies can cause glitches.
7401static int64_t in_get_mmap_time_offset() {
7402 const int32_t kDefaultOffsetMicros = 0;
7403 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007404 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007405 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7406 return mmap_time_offset_micros * (int64_t)1000;
7407}
7408
Haynes Mathew George16081042017-05-31 17:16:49 -07007409static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7410 int32_t min_size_frames,
7411 struct audio_mmap_buffer_info *info)
7412{
7413 struct stream_in *in = (struct stream_in *)stream;
7414 struct audio_device *adev = in->dev;
7415 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007416 unsigned int offset1 = 0;
7417 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007418 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007419 uint32_t mmap_size = 0;
7420 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007421
7422 pthread_mutex_lock(&adev->lock);
7423 ALOGV("%s in %p", __func__, in);
7424
Sharad Sanglec6f32552018-05-04 16:15:38 +05307425 if (CARD_STATUS_OFFLINE == in->card_status||
7426 CARD_STATUS_OFFLINE == adev->card_status) {
7427 ALOGW("in->card_status or adev->card_status offline, try again");
7428 ret = -EIO;
7429 goto exit;
7430 }
7431
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307432 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007433 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7434 ret = -EINVAL;
7435 goto exit;
7436 }
7437 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7438 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7439 ALOGV("%s in %p", __func__, in);
7440 ret = -ENOSYS;
7441 goto exit;
7442 }
7443 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7444 if (in->pcm_device_id < 0) {
7445 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7446 __func__, in->pcm_device_id, in->usecase);
7447 ret = -EINVAL;
7448 goto exit;
7449 }
7450
7451 adjust_mmap_period_count(&in->config, min_size_frames);
7452
7453 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7454 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7455 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7456 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307457 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307458 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7459 in->card_status = CARD_STATUS_OFFLINE;
7460 adev->card_status = CARD_STATUS_OFFLINE;
7461 ret = -EIO;
7462 goto exit;
7463 }
7464
Haynes Mathew George16081042017-05-31 17:16:49 -07007465 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7466 step = "open";
7467 ret = -ENODEV;
7468 goto exit;
7469 }
7470
7471 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7472 if (ret < 0) {
7473 step = "begin";
7474 goto exit;
7475 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007476
juyuchen626833d2019-06-04 16:48:02 +08007477 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007478 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7479 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7480 info->burst_size_frames = in->config.period_size;
7481 ret = platform_get_mmap_data_fd(adev->platform,
7482 in->pcm_device_id, 1 /*capture*/,
7483 &info->shared_memory_fd,
7484 &mmap_size);
7485 if (ret < 0) {
7486 // Fall back to non exclusive mode
7487 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7488 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007489 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7490 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7491
Arun Mirpuri5d170872019-03-26 13:21:31 -07007492 if (mmap_size < buffer_size) {
7493 step = "mmap";
7494 goto exit;
7495 }
juyuchen626833d2019-06-04 16:48:02 +08007496 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007497 }
7498
7499 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007500
7501 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7502 if (ret < 0) {
7503 step = "commit";
7504 goto exit;
7505 }
7506
Phil Burke0a86d12019-02-16 22:28:11 -08007507 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7508
Haynes Mathew George16081042017-05-31 17:16:49 -07007509 in->standby = false;
7510 ret = 0;
7511
7512 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7513 __func__, info->shared_memory_address, info->buffer_size_frames);
7514
7515exit:
7516 if (ret != 0) {
7517 if (in->pcm == NULL) {
7518 ALOGE("%s: %s - %d", __func__, step, ret);
7519 } else {
7520 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7521 pcm_close(in->pcm);
7522 in->pcm = NULL;
7523 }
7524 }
7525 pthread_mutex_unlock(&adev->lock);
7526 return ret;
7527}
7528
7529static int in_get_mmap_position(const struct audio_stream_in *stream,
7530 struct audio_mmap_position *position)
7531{
7532 struct stream_in *in = (struct stream_in *)stream;
7533 ALOGVV("%s", __func__);
7534 if (position == NULL) {
7535 return -EINVAL;
7536 }
7537 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7538 return -ENOSYS;
7539 }
7540 if (in->pcm == NULL) {
7541 return -ENOSYS;
7542 }
7543 struct timespec ts = { 0, 0 };
7544 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7545 if (ret < 0) {
7546 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7547 return ret;
7548 }
Phil Burke0a86d12019-02-16 22:28:11 -08007549 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7550 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007551 return 0;
7552}
7553
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307554static int in_get_active_microphones(const struct audio_stream_in *stream,
7555 struct audio_microphone_characteristic_t *mic_array,
7556 size_t *mic_count) {
7557 struct stream_in *in = (struct stream_in *)stream;
7558 struct audio_device *adev = in->dev;
7559 ALOGVV("%s", __func__);
7560
7561 lock_input_stream(in);
7562 pthread_mutex_lock(&adev->lock);
7563 int ret = platform_get_active_microphones(adev->platform,
7564 audio_channel_count_from_in_mask(in->channel_mask),
7565 in->usecase, mic_array, mic_count);
7566 pthread_mutex_unlock(&adev->lock);
7567 pthread_mutex_unlock(&in->lock);
7568
7569 return ret;
7570}
7571
7572static int adev_get_microphones(const struct audio_hw_device *dev,
7573 struct audio_microphone_characteristic_t *mic_array,
7574 size_t *mic_count) {
7575 struct audio_device *adev = (struct audio_device *)dev;
7576 ALOGVV("%s", __func__);
7577
7578 pthread_mutex_lock(&adev->lock);
7579 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7580 pthread_mutex_unlock(&adev->lock);
7581
7582 return ret;
7583}
juyuchendb308c22019-01-21 11:57:17 -07007584
7585static void in_update_sink_metadata(struct audio_stream_in *stream,
7586 const struct sink_metadata *sink_metadata) {
7587
7588 if (stream == NULL
7589 || sink_metadata == NULL
7590 || sink_metadata->tracks == NULL) {
7591 return;
7592 }
7593
7594 int error = 0;
7595 struct stream_in *in = (struct stream_in *)stream;
7596 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007597 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007598 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007599
7600 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007601
7602 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007603 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007604
7605 lock_input_stream(in);
7606 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007607 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007608
Zhou Song62ea0282020-03-22 19:53:01 +08007609 is_ha_usecase = adev->ha_proxy_enable ?
7610 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7611 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7612 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007613 && adev->voice_tx_output != NULL) {
7614 /* Use the rx device from afe-proxy record to route voice call because
7615 there is no routing if tx device is on primary hal and rx device
7616 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007617 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007618
7619 if (!voice_is_call_state_active(adev)) {
7620 if (adev->mode == AUDIO_MODE_IN_CALL) {
7621 adev->current_call_output = adev->voice_tx_output;
7622 error = voice_start_call(adev);
7623 if (error != 0)
7624 ALOGE("%s: start voice call failed %d", __func__, error);
7625 }
7626 } else {
7627 adev->current_call_output = adev->voice_tx_output;
7628 voice_update_devices_for_all_voice_usecases(adev);
7629 }
7630 }
7631
7632 pthread_mutex_unlock(&adev->lock);
7633 pthread_mutex_unlock(&in->lock);
7634}
7635
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307636int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007637 audio_io_handle_t handle,
7638 audio_devices_t devices,
7639 audio_output_flags_t flags,
7640 struct audio_config *config,
7641 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007642 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007643{
7644 struct audio_device *adev = (struct audio_device *)dev;
7645 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307646 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007647 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007648 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307649 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007650 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7651 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7652 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7653 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007654 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007655 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7656 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007657 bool force_haptic_path =
7658 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007659 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007660
kunleizdff872d2018-08-20 14:40:33 +08007661 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007662 is_usb_dev = false;
7663 devices = AUDIO_DEVICE_OUT_SPEAKER;
7664 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7665 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007666 if (config->format == AUDIO_FORMAT_DEFAULT)
7667 config->format = AUDIO_FORMAT_PCM_16_BIT;
7668 if (config->sample_rate == 0)
7669 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7670 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7671 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007672 }
7673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007674 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307675
Rahul Sharma99770982019-03-06 17:05:26 +05307676 pthread_mutex_lock(&adev->lock);
7677 if (out_get_stream(adev, handle) != NULL) {
7678 ALOGW("%s, output stream already opened", __func__);
7679 ret = -EEXIST;
7680 }
7681 pthread_mutex_unlock(&adev->lock);
7682 if (ret)
7683 return ret;
7684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007685 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7686
Mingming Yin3a941d42016-02-17 18:08:05 -08007687 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007688 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7689 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307690
7691
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007692 if (!out) {
7693 return -ENOMEM;
7694 }
7695
Haynes Mathew George204045b2015-02-25 20:32:03 -08007696 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007697 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307698 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007699 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007700 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007702 if (devices == AUDIO_DEVICE_NONE)
7703 devices = AUDIO_DEVICE_OUT_SPEAKER;
7704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007705 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007706 list_init(&out->device_list);
7707 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007708 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007709 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007710 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307711 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307712 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7713 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7714 else
7715 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007716 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007717 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007718 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307719 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307720 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307721 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007722 out->hal_output_suspend_supported = 0;
7723 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307724 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307725 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307726 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007727 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007728
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307729 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307730 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007731 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7732
Aalique Grahame22e49102018-12-18 14:23:57 -08007733 if (direct_dev &&
7734 (audio_is_linear_pcm(out->format) ||
7735 config->format == AUDIO_FORMAT_DEFAULT) &&
7736 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7737 audio_format_t req_format = config->format;
7738 audio_channel_mask_t req_channel_mask = config->channel_mask;
7739 uint32_t req_sample_rate = config->sample_rate;
7740
7741 pthread_mutex_lock(&adev->lock);
7742 if (is_hdmi) {
7743 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7744 ret = read_hdmi_sink_caps(out);
7745 if (config->sample_rate == 0)
7746 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7747 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7748 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7749 if (config->format == AUDIO_FORMAT_DEFAULT)
7750 config->format = AUDIO_FORMAT_PCM_16_BIT;
7751 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007752 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7753 &config->format,
7754 &out->supported_formats[0],
7755 MAX_SUPPORTED_FORMATS,
7756 &config->channel_mask,
7757 &out->supported_channel_masks[0],
7758 MAX_SUPPORTED_CHANNEL_MASKS,
7759 &config->sample_rate,
7760 &out->supported_sample_rates[0],
7761 MAX_SUPPORTED_SAMPLE_RATES);
7762 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007763 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007764
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007765 pthread_mutex_unlock(&adev->lock);
7766 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007767 if (ret == -ENOSYS) {
7768 /* ignore and go with default */
7769 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007770 }
7771 // For MMAP NO IRQ, allow conversions in ADSP
7772 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7773 goto error_open;
7774 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007775 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007776 goto error_open;
7777 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007778
7779 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7780 config->sample_rate = req_sample_rate;
7781 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7782 config->channel_mask = req_channel_mask;
7783 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7784 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007785 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007786
7787 out->sample_rate = config->sample_rate;
7788 out->channel_mask = config->channel_mask;
7789 out->format = config->format;
7790 if (is_hdmi) {
7791 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7792 out->config = pcm_config_hdmi_multi;
7793 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7794 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7795 out->config = pcm_config_mmap_playback;
7796 out->stream.start = out_start;
7797 out->stream.stop = out_stop;
7798 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7799 out->stream.get_mmap_position = out_get_mmap_position;
7800 } else {
7801 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7802 out->config = pcm_config_hifi;
7803 }
7804
7805 out->config.rate = out->sample_rate;
7806 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7807 if (is_hdmi) {
7808 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7809 audio_bytes_per_sample(out->format));
7810 }
7811 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007812 }
7813
Derek Chenf6318be2017-06-12 17:16:24 -04007814 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007815 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007816 /* extract car audio stream index */
7817 out->car_audio_stream =
7818 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7819 if (out->car_audio_stream < 0) {
7820 ALOGE("%s: invalid car audio stream %x",
7821 __func__, out->car_audio_stream);
7822 ret = -EINVAL;
7823 goto error_open;
7824 }
Derek Chen5f67a942020-02-24 23:08:13 -08007825 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007826 }
7827
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007828 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007829 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007830 if (!voice_extn_is_compress_voip_supported()) {
7831 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7832 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007833 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307834 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007835 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7836 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007837 out->volume_l = INVALID_OUT_VOLUME;
7838 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007839
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007840 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007841 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007842 uint32_t channel_count =
7843 audio_channel_count_from_out_mask(out->channel_mask);
7844 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7845 out->sample_rate, out->format,
7846 channel_count, false);
7847 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7848 if (frame_size != 0)
7849 out->config.period_size = buffer_size / frame_size;
7850 else
7851 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007852 }
7853 } else {
7854 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7855 voice_extn_compress_voip_is_active(out->dev)) &&
7856 (voice_extn_compress_voip_is_config_supported(config))) {
7857 ret = voice_extn_compress_voip_open_output_stream(out);
7858 if (ret != 0) {
7859 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7860 __func__, ret);
7861 goto error_open;
7862 }
Sujin Panicker19027262019-09-16 18:28:06 +05307863 } else {
7864 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7865 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007866 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007867 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007868 } else if (audio_is_linear_pcm(out->format) &&
7869 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7870 out->channel_mask = config->channel_mask;
7871 out->sample_rate = config->sample_rate;
7872 out->format = config->format;
7873 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7874 // does this change?
7875 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7876 out->config.rate = config->sample_rate;
7877 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7878 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7879 audio_bytes_per_sample(config->format));
7880 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007881 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307882 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307883 pthread_mutex_lock(&adev->lock);
7884 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7885 pthread_mutex_unlock(&adev->lock);
7886
7887 // reject offload during card offline to allow
7888 // fallback to s/w paths
7889 if (offline) {
7890 ret = -ENODEV;
7891 goto error_open;
7892 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007893
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007894 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7895 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7896 ALOGE("%s: Unsupported Offload information", __func__);
7897 ret = -EINVAL;
7898 goto error_open;
7899 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007900
Atul Khare3fa6e542017-08-09 00:56:17 +05307901 if (config->offload_info.format == 0)
7902 config->offload_info.format = config->format;
7903 if (config->offload_info.sample_rate == 0)
7904 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007905
Mingming Yin90310102013-11-13 16:57:00 -08007906 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307907 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007908 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007909 ret = -EINVAL;
7910 goto error_open;
7911 }
7912
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007913 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7914 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7915 (audio_extn_passthru_is_passthrough_stream(out)) &&
7916 !((config->sample_rate == 48000) ||
7917 (config->sample_rate == 96000) ||
7918 (config->sample_rate == 192000))) {
7919 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7920 __func__, config->sample_rate, config->offload_info.format);
7921 ret = -EINVAL;
7922 goto error_open;
7923 }
7924
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007925 out->compr_config.codec = (struct snd_codec *)
7926 calloc(1, sizeof(struct snd_codec));
7927
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007928 if (!out->compr_config.codec) {
7929 ret = -ENOMEM;
7930 goto error_open;
7931 }
7932
Dhananjay Kumarac341582017-02-23 23:42:25 +05307933 out->stream.pause = out_pause;
7934 out->stream.resume = out_resume;
7935 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307936 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307937 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007938 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307939 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007940 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307941 } else {
7942 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7943 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007944 }
vivek mehta446c3962015-09-14 10:57:35 -07007945
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307946 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7947 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007948#ifdef AUDIO_GKI_ENABLED
7949 /* out->compr_config.codec->reserved[1] is for flags */
7950 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7951#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307952 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007953#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307954 }
7955
vivek mehta446c3962015-09-14 10:57:35 -07007956 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007957 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007958 config->format == 0 && config->sample_rate == 0 &&
7959 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007960 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007961 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7962 } else {
7963 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7964 ret = -EEXIST;
7965 goto error_open;
7966 }
vivek mehta446c3962015-09-14 10:57:35 -07007967 }
7968
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007969 if (config->offload_info.channel_mask)
7970 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007971 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007972 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007973 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007974 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307975 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007976 ret = -EINVAL;
7977 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007978 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007979
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007980 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007981 out->sample_rate = config->offload_info.sample_rate;
7982
Mingming Yin3ee55c62014-08-04 14:23:35 -07007983 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007984
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307985 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307986 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307987 audio_extn_dolby_send_ddp_endp_params(adev);
7988 audio_extn_dolby_set_dmid(adev);
7989 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007990
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007991 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007992 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007993 out->compr_config.codec->bit_rate =
7994 config->offload_info.bit_rate;
7995 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307996 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007997 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307998 /* Update bit width only for non passthrough usecases.
7999 * For passthrough usecases, the output will always be opened @16 bit
8000 */
8001 if (!audio_extn_passthru_is_passthrough_stream(out))
8002 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308003
8004 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008005#ifdef AUDIO_GKI_ENABLED
8006 /* out->compr_config.codec->reserved[1] is for flags */
8007 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8008 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8009#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308010 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8011 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008012#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308013
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008014 /*TODO: Do we need to change it for passthrough */
8015 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008016
Manish Dewangana6fc5442015-08-24 20:30:31 +05308017 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8018 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308019 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308020 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308021 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8022 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308023
8024 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8025 AUDIO_FORMAT_PCM) {
8026
8027 /*Based on platform support, configure appropriate alsa format for corresponding
8028 *hal input format.
8029 */
8030 out->compr_config.codec->format = hal_format_to_alsa(
8031 config->offload_info.format);
8032
Ashish Jain83a6cc22016-06-28 14:34:17 +05308033 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308034 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308035 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308036
Dhananjay Kumarac341582017-02-23 23:42:25 +05308037 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308038 *hal input format and alsa format might differ based on platform support.
8039 */
8040 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308041 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308042
8043 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8044
Deeraj Soman93155a62019-09-30 19:00:37 +05308045 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8046 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8047 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8048 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8049 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308050
Ashish Jainf1eaa582016-05-23 20:54:24 +05308051 /* Check if alsa session is configured with the same format as HAL input format,
8052 * if not then derive correct fragment size needed to accomodate the
8053 * conversion of HAL input format to alsa format.
8054 */
8055 audio_extn_utils_update_direct_pcm_fragment_size(out);
8056
8057 /*if hal input and output fragment size is different this indicates HAL input format is
8058 *not same as the alsa format
8059 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308060 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308061 /*Allocate a buffer to convert input data to the alsa configured format.
8062 *size of convert buffer is equal to the size required to hold one fragment size
8063 *worth of pcm data, this is because flinger does not write more than fragment_size
8064 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308065 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8066 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308067 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8068 ret = -ENOMEM;
8069 goto error_open;
8070 }
8071 }
8072 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8073 out->compr_config.fragment_size =
8074 audio_extn_passthru_get_buffer_size(&config->offload_info);
8075 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8076 } else {
8077 out->compr_config.fragment_size =
8078 platform_get_compress_offload_buffer_size(&config->offload_info);
8079 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8080 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008081
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308082 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8083 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8084 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07008085 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308086 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008087
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308088 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8089 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8090 }
8091
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008092 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8093 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008094
Manish Dewangan69426c82017-01-30 17:35:36 +05308095 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8096 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8097 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8098 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8099 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8100 } else {
8101 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8102 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008103
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308104 memset(&out->channel_map_param, 0,
8105 sizeof(struct audio_out_channel_map_param));
8106
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008107 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308108 out->send_next_track_params = false;
8109 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008110 out->offload_state = OFFLOAD_STATE_IDLE;
8111 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008112 out->writeAt.tv_sec = 0;
8113 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008114
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008115 audio_extn_dts_create_state_notifier_node(out->usecase);
8116
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008117 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8118 __func__, config->offload_info.version,
8119 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308120
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308121 /* Check if DSD audio format is supported in codec
8122 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308123 */
8124
8125 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308126 (!platform_check_codec_dsd_support(adev->platform) ||
8127 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308128 ret = -EINVAL;
8129 goto error_open;
8130 }
8131
Ashish Jain5106d362016-05-11 19:23:33 +05308132 /* Disable gapless if any of the following is true
8133 * passthrough playback
8134 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308135 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308136 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308137 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308138 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008139 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308140 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308141 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308142 check_and_set_gapless_mode(adev, false);
8143 } else
8144 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008145
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308146 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008147 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8148 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308149 if (config->format == AUDIO_FORMAT_DSD) {
8150 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008151#ifdef AUDIO_GKI_ENABLED
8152 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8153 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8154#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308155 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008156#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308157 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008158
8159 create_offload_callback_thread(out);
8160
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008161 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008162 switch (config->sample_rate) {
8163 case 0:
8164 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8165 break;
8166 case 8000:
8167 case 16000:
8168 case 48000:
8169 out->sample_rate = config->sample_rate;
8170 break;
8171 default:
8172 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8173 config->sample_rate);
8174 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8175 ret = -EINVAL;
8176 goto error_open;
8177 }
8178 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8179 switch (config->channel_mask) {
8180 case AUDIO_CHANNEL_NONE:
8181 case AUDIO_CHANNEL_OUT_STEREO:
8182 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8183 break;
8184 default:
8185 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8186 config->channel_mask);
8187 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8188 ret = -EINVAL;
8189 goto error_open;
8190 }
8191 switch (config->format) {
8192 case AUDIO_FORMAT_DEFAULT:
8193 case AUDIO_FORMAT_PCM_16_BIT:
8194 out->format = AUDIO_FORMAT_PCM_16_BIT;
8195 break;
8196 default:
8197 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8198 config->format);
8199 config->format = AUDIO_FORMAT_PCM_16_BIT;
8200 ret = -EINVAL;
8201 goto error_open;
8202 }
8203
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308204 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008205 if (ret != 0) {
8206 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008207 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008208 goto error_open;
8209 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008210 } else if (is_single_device_type_equal(&out->device_list,
8211 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008212 switch (config->sample_rate) {
8213 case 0:
8214 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8215 break;
8216 case 8000:
8217 case 16000:
8218 case 48000:
8219 out->sample_rate = config->sample_rate;
8220 break;
8221 default:
8222 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8223 config->sample_rate);
8224 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8225 ret = -EINVAL;
8226 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008227 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008228 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8229 switch (config->channel_mask) {
8230 case AUDIO_CHANNEL_NONE:
8231 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8232 break;
8233 case AUDIO_CHANNEL_OUT_STEREO:
8234 out->channel_mask = config->channel_mask;
8235 break;
8236 default:
8237 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8238 config->channel_mask);
8239 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8240 ret = -EINVAL;
8241 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008242 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008243 switch (config->format) {
8244 case AUDIO_FORMAT_DEFAULT:
8245 out->format = AUDIO_FORMAT_PCM_16_BIT;
8246 break;
8247 case AUDIO_FORMAT_PCM_16_BIT:
8248 out->format = config->format;
8249 break;
8250 default:
8251 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8252 config->format);
8253 config->format = AUDIO_FORMAT_PCM_16_BIT;
8254 ret = -EINVAL;
8255 break;
8256 }
8257 if (ret != 0)
8258 goto error_open;
8259
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008260 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8261 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008262 out->config.rate = out->sample_rate;
8263 out->config.channels =
8264 audio_channel_count_from_out_mask(out->channel_mask);
8265 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008266 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008267 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308268 unsigned int channels = 0;
8269 /*Update config params to default if not set by the caller*/
8270 if (config->sample_rate == 0)
8271 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8272 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8273 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8274 if (config->format == AUDIO_FORMAT_DEFAULT)
8275 config->format = AUDIO_FORMAT_PCM_16_BIT;
8276
8277 channels = audio_channel_count_from_out_mask(out->channel_mask);
8278
Varun Balaraje49253e2017-07-06 19:48:56 +05308279 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8280 out->usecase = get_interactive_usecase(adev);
8281 out->config = pcm_config_low_latency;
8282 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308283 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008284 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8285 out->flags);
8286 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008287 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8288 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8289 out->config = pcm_config_mmap_playback;
8290 out->stream.start = out_start;
8291 out->stream.stop = out_stop;
8292 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8293 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308294 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8295 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008296 out->hal_output_suspend_supported =
8297 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8298 out->dynamic_pm_qos_config_supported =
8299 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8300 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008301 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8302 } else {
8303 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8304 //the mixer path will be a string similar to "low-latency-playback resume"
8305 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8306 strlcat(out->pm_qos_mixer_path,
8307 " resume", MAX_MIXER_PATH_LEN);
8308 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8309 out->pm_qos_mixer_path);
8310 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308311 out->config = pcm_config_low_latency;
8312 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8313 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8314 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308315 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8316 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8317 if (out->config.period_size <= 0) {
8318 ALOGE("Invalid configuration period size is not valid");
8319 ret = -EINVAL;
8320 goto error_open;
8321 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008322 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8323 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8324 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008325 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8326 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8327 out->config = pcm_config_haptics_audio;
8328 if (force_haptic_path)
8329 adev->haptics_config = pcm_config_haptics_audio;
8330 else
8331 adev->haptics_config = pcm_config_haptics;
8332
Meng Wangd08ce322020-04-02 08:59:20 +08008333 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008334 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8335
8336 if (force_haptic_path) {
8337 out->config.channels = 1;
8338 adev->haptics_config.channels = 1;
8339 } else
8340 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 -08008341 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008342 ret = audio_extn_auto_hal_open_output_stream(out);
8343 if (ret) {
8344 ALOGE("%s: Failed to open output stream for bus device", __func__);
8345 ret = -EINVAL;
8346 goto error_open;
8347 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308348 } else {
8349 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008350 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8351 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308352 }
8353 out->hal_ip_format = format = out->format;
8354 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8355 out->hal_op_format = pcm_format_to_hal(out->config.format);
8356 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8357 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008358 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308359 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308360 if (out->hal_ip_format != out->hal_op_format) {
8361 uint32_t buffer_size = out->config.period_size *
8362 format_to_bitwidth_table[out->hal_op_format] *
8363 out->config.channels;
8364 out->convert_buffer = calloc(1, buffer_size);
8365 if (out->convert_buffer == NULL){
8366 ALOGE("Allocation failed for convert buffer for size %d",
8367 out->compr_config.fragment_size);
8368 ret = -ENOMEM;
8369 goto error_open;
8370 }
8371 ALOGD("Convert buffer allocated of size %d", buffer_size);
8372 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008373 }
8374
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008375 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8376 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308377
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008378 /* TODO remove this hardcoding and check why width is zero*/
8379 if (out->bit_width == 0)
8380 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308381 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008382 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008383 &out->device_list, out->flags,
8384 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308385 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308386 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008387 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008388 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8389 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008390 if(adev->primary_output == NULL)
8391 adev->primary_output = out;
8392 else {
8393 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008394 ret = -EEXIST;
8395 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008396 }
8397 }
8398
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008399 /* Check if this usecase is already existing */
8400 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008401 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8402 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008403 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008404 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008405 ret = -EEXIST;
8406 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008407 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008409 pthread_mutex_unlock(&adev->lock);
8410
8411 out->stream.common.get_sample_rate = out_get_sample_rate;
8412 out->stream.common.set_sample_rate = out_set_sample_rate;
8413 out->stream.common.get_buffer_size = out_get_buffer_size;
8414 out->stream.common.get_channels = out_get_channels;
8415 out->stream.common.get_format = out_get_format;
8416 out->stream.common.set_format = out_set_format;
8417 out->stream.common.standby = out_standby;
8418 out->stream.common.dump = out_dump;
8419 out->stream.common.set_parameters = out_set_parameters;
8420 out->stream.common.get_parameters = out_get_parameters;
8421 out->stream.common.add_audio_effect = out_add_audio_effect;
8422 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8423 out->stream.get_latency = out_get_latency;
8424 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008425#ifdef NO_AUDIO_OUT
8426 out->stream.write = out_write_for_no_output;
8427#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008428 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008429#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008430 out->stream.get_render_position = out_get_render_position;
8431 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008432 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008433
Haynes Mathew George16081042017-05-31 17:16:49 -07008434 if (out->realtime)
8435 out->af_period_multiplier = af_period_multiplier;
8436 else
8437 out->af_period_multiplier = 1;
8438
Andy Hunga1f48fa2019-07-01 18:14:53 -07008439 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008441 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008442 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008443 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008444
8445 config->format = out->stream.common.get_format(&out->stream.common);
8446 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8447 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308448 register_format(out->format, out->supported_formats);
8449 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8450 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008451
Aalique Grahame22e49102018-12-18 14:23:57 -08008452 out->error_log = error_log_create(
8453 ERROR_LOG_ENTRIES,
8454 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8455
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308456 /*
8457 By locking output stream before registering, we allow the callback
8458 to update stream's state only after stream's initial state is set to
8459 adev state.
8460 */
8461 lock_output_stream(out);
8462 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8463 pthread_mutex_lock(&adev->lock);
8464 out->card_status = adev->card_status;
8465 pthread_mutex_unlock(&adev->lock);
8466 pthread_mutex_unlock(&out->lock);
8467
Aalique Grahame22e49102018-12-18 14:23:57 -08008468 stream_app_type_cfg_init(&out->app_type_cfg);
8469
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008470 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308471 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008472 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008473
8474 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8475 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8476 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008477 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308478 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008479 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008480 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308481 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8482 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008483 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8484 out->usecase, PCM_PLAYBACK);
8485 hdlr_stream_cfg.flags = out->flags;
8486 hdlr_stream_cfg.type = PCM_PLAYBACK;
8487 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8488 &hdlr_stream_cfg);
8489 if (ret) {
8490 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8491 out->adsp_hdlr_stream_handle = NULL;
8492 }
8493 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308494 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8495 is_direct_passthough, false);
8496 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8497 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008498 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008499 if (ret < 0) {
8500 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8501 out->ip_hdlr_handle = NULL;
8502 }
8503 }
Derek Chenf939fb72018-11-13 13:34:41 -08008504
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008505 ret = io_streams_map_insert(adev, &out->stream.common,
8506 out->handle, AUDIO_PATCH_HANDLE_NONE);
8507 if (ret != 0)
8508 goto error_open;
8509
Derek Chenf939fb72018-11-13 13:34:41 -08008510 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8511 calloc(1, sizeof(streams_output_ctxt_t));
8512 if (out_ctxt == NULL) {
8513 ALOGE("%s fail to allocate output ctxt", __func__);
8514 ret = -ENOMEM;
8515 goto error_open;
8516 }
8517 out_ctxt->output = out;
8518
8519 pthread_mutex_lock(&adev->lock);
8520 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8521 pthread_mutex_unlock(&adev->lock);
8522
Eric Laurent994a6932013-07-17 11:51:42 -07008523 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008524 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008525
8526error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308527 if (out->convert_buffer)
8528 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008529 free(out);
8530 *stream_out = NULL;
8531 ALOGD("%s: exit: ret %d", __func__, ret);
8532 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008533}
8534
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308535void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008536 struct audio_stream_out *stream)
8537{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008538 struct stream_out *out = (struct stream_out *)stream;
8539 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008540 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008541
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008542 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308543
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008544 io_streams_map_remove(adev, out->handle);
8545
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308546 // must deregister from sndmonitor first to prevent races
8547 // between the callback and close_stream
8548 audio_extn_snd_mon_unregister_listener(out);
8549
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008550 /* close adsp hdrl session before standby */
8551 if (out->adsp_hdlr_stream_handle) {
8552 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8553 if (ret)
8554 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8555 out->adsp_hdlr_stream_handle = NULL;
8556 }
8557
Manish Dewangan21a850a2017-08-14 12:03:55 +05308558 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008559 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8560 out->ip_hdlr_handle = NULL;
8561 }
8562
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008563 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308564 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008565 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308566 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308567 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008568 if(ret != 0)
8569 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8570 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008571 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008572 out_standby(&stream->common);
8573
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008574 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008575 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008576 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008577 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008578 if (out->compr_config.codec != NULL)
8579 free(out->compr_config.codec);
8580 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008581
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308582 out->a2dp_compress_mute = false;
8583
Varun Balaraje49253e2017-07-06 19:48:56 +05308584 if (is_interactive_usecase(out->usecase))
8585 free_interactive_usecase(adev, out->usecase);
8586
Ashish Jain83a6cc22016-06-28 14:34:17 +05308587 if (out->convert_buffer != NULL) {
8588 free(out->convert_buffer);
8589 out->convert_buffer = NULL;
8590 }
8591
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008592 if (adev->voice_tx_output == out)
8593 adev->voice_tx_output = NULL;
8594
Aalique Grahame22e49102018-12-18 14:23:57 -08008595 error_log_destroy(out->error_log);
8596 out->error_log = NULL;
8597
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308598 if (adev->primary_output == out)
8599 adev->primary_output = NULL;
8600
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008601 pthread_cond_destroy(&out->cond);
8602 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008603
8604 pthread_mutex_lock(&adev->lock);
8605 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8606 if (out_ctxt != NULL) {
8607 list_remove(&out_ctxt->list);
8608 free(out_ctxt);
8609 } else {
8610 ALOGW("%s, output stream already closed", __func__);
8611 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008612 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008613 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008614 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008615}
8616
8617static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8618{
8619 struct audio_device *adev = (struct audio_device *)dev;
8620 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008621 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008622 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008623 int ret;
8624 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008625 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008626 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008627 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008628
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008629 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008630 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008631
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308632 if (!parms)
8633 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308634
Derek Chen6f293672019-04-01 01:40:24 -07008635 /* notify adev and input/output streams on the snd card status */
8636 adev_snd_mon_cb((void *)adev, parms);
8637
8638 list_for_each(node, &adev->active_outputs_list) {
8639 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8640 streams_output_ctxt_t,
8641 list);
8642 out_snd_mon_cb((void *)out_ctxt->output, parms);
8643 }
8644
8645 list_for_each(node, &adev->active_inputs_list) {
8646 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8647 streams_input_ctxt_t,
8648 list);
8649 in_snd_mon_cb((void *)in_ctxt->input, parms);
8650 }
8651
Zhou Songd6d71752019-05-21 18:08:51 +08008652 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308653 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8654 if (ret >= 0) {
8655 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008656 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308657 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008658 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308659 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008660 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008661 }
8662 }
8663
8664 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8665 if (ret>=0) {
8666 if (!strncmp(value, "false", 5) &&
8667 audio_extn_a2dp_source_is_suspended()) {
8668 struct audio_usecase *usecase;
8669 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008670 list_for_each(node, &adev->usecase_list) {
8671 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008672 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008673 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008674 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008675 reassign_device_list(&usecase->stream.in->device_list,
8676 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008677 select_devices(adev, usecase->id);
8678 }
Zhou Songd6d71752019-05-21 18:08:51 +08008679 }
8680 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308681 }
8682
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008683 status = voice_set_parameters(adev, parms);
8684 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008685 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008686
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008687 status = platform_set_parameters(adev->platform, parms);
8688 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008689 goto done;
8690
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008691 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8692 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008693 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008694 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8695 adev->bluetooth_nrec = true;
8696 else
8697 adev->bluetooth_nrec = false;
8698 }
8699
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008700 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8701 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008702 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8703 adev->screen_off = false;
8704 else
8705 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008706 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008707 }
8708
Eric Laurent4b084132018-10-19 17:33:43 -07008709 ret = str_parms_get_int(parms, "rotation", &val);
8710 if (ret >= 0) {
8711 bool reverse_speakers = false;
8712 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8713 switch (val) {
8714 // FIXME: note that the code below assumes that the speakers are in the correct placement
8715 // relative to the user when the device is rotated 90deg from its default rotation. This
8716 // assumption is device-specific, not platform-specific like this code.
8717 case 270:
8718 reverse_speakers = true;
8719 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8720 break;
8721 case 0:
8722 case 180:
8723 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8724 break;
8725 case 90:
8726 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8727 break;
8728 default:
8729 ALOGE("%s: unexpected rotation of %d", __func__, val);
8730 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008731 }
Eric Laurent4b084132018-10-19 17:33:43 -07008732 if (status == 0) {
8733 // check and set swap
8734 // - check if orientation changed and speaker active
8735 // - set rotation and cache the rotation value
8736 adev->camera_orientation =
8737 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8738 if (!audio_extn_is_maxx_audio_enabled())
8739 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8740 }
8741 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008742
Mingming Yin514a8bc2014-07-29 15:22:21 -07008743 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8744 if (ret >= 0) {
8745 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8746 adev->bt_wb_speech_enabled = true;
8747 else
8748 adev->bt_wb_speech_enabled = false;
8749 }
8750
Zhou Song12c29502019-03-16 10:37:18 +08008751 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8752 if (ret >= 0) {
8753 val = atoi(value);
8754 adev->swb_speech_mode = val;
8755 }
8756
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008757 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8758 if (ret >= 0) {
8759 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308760 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008761 if (audio_is_output_device(val) &&
8762 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008763 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008764 platform_get_controller_stream_from_params(parms, &controller, &stream);
8765 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8766 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008767 if (ret < 0) {
8768 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308769 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008770 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008771 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308772 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008773 /*
8774 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8775 * Per AudioPolicyManager, USB device is higher priority than WFD.
8776 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8777 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8778 * starting voice call on USB
8779 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008780 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308781 if (ret >= 0)
8782 audio_extn_usb_add_device(device, atoi(value));
8783
Zhou Song6f862822017-11-06 17:27:57 +08008784 if (!audio_extn_usb_is_tunnel_supported()) {
8785 ALOGV("detected USB connect .. disable proxy");
8786 adev->allow_afe_proxy_usage = false;
8787 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008788 }
8789 }
8790
8791 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8792 if (ret >= 0) {
8793 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308794 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008795 /*
8796 * The HDMI / Displayport disconnect handling has been moved to
8797 * audio extension to ensure that its parameters are not
8798 * invalidated prior to updating sysfs of the disconnect event
8799 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8800 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308801 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008802 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308803 if (ret >= 0)
8804 audio_extn_usb_remove_device(device, atoi(value));
8805
Zhou Song6f862822017-11-06 17:27:57 +08008806 if (!audio_extn_usb_is_tunnel_supported()) {
8807 ALOGV("detected USB disconnect .. enable proxy");
8808 adev->allow_afe_proxy_usage = true;
8809 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008810 }
8811 }
8812
Aalique Grahame22e49102018-12-18 14:23:57 -08008813 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008814 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008815
8816 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008817 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308818 struct audio_usecase *usecase;
8819 struct listnode *node;
8820 list_for_each(node, &adev->usecase_list) {
8821 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008822 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8823 continue;
8824
8825 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308826 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008827 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308828 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008829 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308830 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308831 ALOGD("Switching to speaker and muting the stream before select_devices");
8832 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308833 //force device switch to re configure encoder
8834 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308835 ALOGD("Unmuting the stream after select_devices");
8836 usecase->stream.out->a2dp_compress_mute = false;
8837 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 +05308838 audio_extn_a2dp_set_handoff_mode(false);
8839 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308840 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308841 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8842 usecase->stream.out->a2dp_compress_mute) {
8843 pthread_mutex_unlock(&adev->lock);
8844 lock_output_stream(usecase->stream.out);
8845 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008846 reassign_device_list(&usecase->stream.out->device_list,
8847 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308848 check_a2dp_restore_l(adev, usecase->stream.out, true);
8849 pthread_mutex_unlock(&usecase->stream.out->lock);
8850 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308851 }
8852 }
8853 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008854
8855 //handle vr audio setparam
8856 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8857 value, sizeof(value));
8858 if (ret >= 0) {
8859 ALOGI("Setting vr mode to be %s", value);
8860 if (!strncmp(value, "true", 4)) {
8861 adev->vr_audio_mode_enabled = true;
8862 ALOGI("Setting vr mode to true");
8863 } else if (!strncmp(value, "false", 5)) {
8864 adev->vr_audio_mode_enabled = false;
8865 ALOGI("Setting vr mode to false");
8866 } else {
8867 ALOGI("wrong vr mode set");
8868 }
8869 }
8870
Eric Laurent4b084132018-10-19 17:33:43 -07008871 //FIXME: to be replaced by proper video capture properties API
8872 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8873 if (ret >= 0) {
8874 int camera_facing = CAMERA_FACING_BACK;
8875 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8876 camera_facing = CAMERA_FACING_FRONT;
8877 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8878 camera_facing = CAMERA_FACING_BACK;
8879 else {
8880 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8881 goto done;
8882 }
8883 adev->camera_orientation =
8884 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8885 struct audio_usecase *usecase;
8886 struct listnode *node;
8887 list_for_each(node, &adev->usecase_list) {
8888 usecase = node_to_item(node, struct audio_usecase, list);
8889 struct stream_in *in = usecase->stream.in;
8890 if (usecase->type == PCM_CAPTURE && in != NULL &&
8891 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8892 select_devices(adev, in->usecase);
8893 }
8894 }
8895 }
8896
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308897 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008898done:
8899 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008900 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308901error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008902 ALOGV("%s: exit with code(%d)", __func__, status);
8903 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008904}
8905
8906static char* adev_get_parameters(const struct audio_hw_device *dev,
8907 const char *keys)
8908{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308909 ALOGD("%s:%s", __func__, keys);
8910
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008911 struct audio_device *adev = (struct audio_device *)dev;
8912 struct str_parms *reply = str_parms_create();
8913 struct str_parms *query = str_parms_create_str(keys);
8914 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308915 char value[256] = {0};
8916 int ret = 0;
8917
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008918 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008919 if (reply) {
8920 str_parms_destroy(reply);
8921 }
8922 if (query) {
8923 str_parms_destroy(query);
8924 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008925 ALOGE("adev_get_parameters: failed to create query or reply");
8926 return NULL;
8927 }
8928
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008929 //handle vr audio getparam
8930
8931 ret = str_parms_get_str(query,
8932 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8933 value, sizeof(value));
8934
8935 if (ret >= 0) {
8936 bool vr_audio_enabled = false;
8937 pthread_mutex_lock(&adev->lock);
8938 vr_audio_enabled = adev->vr_audio_mode_enabled;
8939 pthread_mutex_unlock(&adev->lock);
8940
8941 ALOGI("getting vr mode to %d", vr_audio_enabled);
8942
8943 if (vr_audio_enabled) {
8944 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8945 "true");
8946 goto exit;
8947 } else {
8948 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8949 "false");
8950 goto exit;
8951 }
8952 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008953
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008954 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008955 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008956 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008957 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008958 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08008959 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308960 pthread_mutex_unlock(&adev->lock);
8961
Naresh Tannirud7205b62014-06-20 02:54:48 +05308962exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008963 str = str_parms_to_str(reply);
8964 str_parms_destroy(query);
8965 str_parms_destroy(reply);
8966
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308967 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008968 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008969}
8970
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008971static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008972{
8973 return 0;
8974}
8975
8976static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8977{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008978 int ret;
8979 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008980
8981 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8982
Haynes Mathew George5191a852013-09-11 14:19:36 -07008983 pthread_mutex_lock(&adev->lock);
8984 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008985 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008986 pthread_mutex_unlock(&adev->lock);
8987 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008988}
8989
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008990static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8991 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008992{
8993 return -ENOSYS;
8994}
8995
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008996static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8997 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008998{
8999 return -ENOSYS;
9000}
9001
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009002static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9003 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009004{
9005 return -ENOSYS;
9006}
9007
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009008static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9009 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009010{
9011 return -ENOSYS;
9012}
9013
9014static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9015{
9016 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009017 struct listnode *node;
9018 struct audio_usecase *usecase = NULL;
9019 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009021 pthread_mutex_lock(&adev->lock);
9022 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309023 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9024 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009025 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05309026 if( mode == AUDIO_MODE_CALL_SCREEN ){
9027 adev->current_call_output = adev->primary_output;
9028 voice_start_call(adev);
9029 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009030 (mode == AUDIO_MODE_NORMAL ||
9031 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009032 list_for_each(node, &adev->usecase_list) {
9033 usecase = node_to_item(node, struct audio_usecase, list);
9034 if (usecase->type == VOICE_CALL)
9035 break;
9036 }
9037 if (usecase &&
9038 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9039 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9040 true);
9041 if (ret != 0) {
9042 /* default service interval was successfully updated,
9043 reopen USB backend with new service interval */
9044 check_usecases_codec_backend(adev,
9045 usecase,
9046 usecase->out_snd_device);
9047 }
9048 }
9049
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009050 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009051 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009052 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009053 // restore device for other active usecases after stop call
9054 list_for_each(node, &adev->usecase_list) {
9055 usecase = node_to_item(node, struct audio_usecase, list);
9056 select_devices(adev, usecase->id);
9057 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009058 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009059 }
9060 pthread_mutex_unlock(&adev->lock);
9061 return 0;
9062}
9063
9064static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9065{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009066 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009067 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009068
9069 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009070 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009071 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009072
Derek Chend2530072014-11-24 12:39:14 -08009073 if (adev->ext_hw_plugin)
9074 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009075
9076 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009077 pthread_mutex_unlock(&adev->lock);
9078
9079 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009080}
9081
9082static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9083{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009084 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009085 return 0;
9086}
9087
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009088static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009089 const struct audio_config *config)
9090{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009091 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009092
Aalique Grahame22e49102018-12-18 14:23:57 -08009093 /* Don't know if USB HIFI in this context so use true to be conservative */
9094 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9095 true /*is_usb_hifi */) != 0)
9096 return 0;
9097
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009098 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9099 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009100}
9101
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009102static bool adev_input_allow_hifi_record(struct audio_device *adev,
9103 audio_devices_t devices,
9104 audio_input_flags_t flags,
9105 audio_source_t source) {
9106 const bool allowed = true;
9107
9108 if (!audio_is_usb_in_device(devices))
9109 return !allowed;
9110
9111 switch (flags) {
9112 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009113 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009114 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9115 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009116 default:
9117 return !allowed;
9118 }
9119
9120 switch (source) {
9121 case AUDIO_SOURCE_DEFAULT:
9122 case AUDIO_SOURCE_MIC:
9123 case AUDIO_SOURCE_UNPROCESSED:
9124 break;
9125 default:
9126 return !allowed;
9127 }
9128
9129 switch (adev->mode) {
9130 case 0:
9131 break;
9132 default:
9133 return !allowed;
9134 }
9135
9136 return allowed;
9137}
9138
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009139static int adev_update_voice_comm_input_stream(struct stream_in *in,
9140 struct audio_config *config)
9141{
9142 bool valid_rate = (config->sample_rate == 8000 ||
9143 config->sample_rate == 16000 ||
9144 config->sample_rate == 32000 ||
9145 config->sample_rate == 48000);
9146 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9147
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009148 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009149 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009150 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9151 in->config = default_pcm_config_voip_copp;
9152 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9153 DEFAULT_VOIP_BUF_DURATION_MS,
9154 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009155 } else {
9156 ALOGW("%s No valid input in voip, use defaults"
9157 "sample rate %u, channel mask 0x%X",
9158 __func__, config->sample_rate, in->channel_mask);
9159 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009160 in->config.rate = config->sample_rate;
9161 in->sample_rate = config->sample_rate;
9162 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009163 //XXX needed for voice_extn_compress_voip_open_input_stream
9164 in->config.rate = config->sample_rate;
9165 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309166 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009167 voice_extn_compress_voip_is_active(in->dev)) &&
9168 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9169 valid_rate && valid_ch) {
9170 voice_extn_compress_voip_open_input_stream(in);
9171 // update rate entries to match config from AF
9172 in->config.rate = config->sample_rate;
9173 in->sample_rate = config->sample_rate;
9174 } else {
9175 ALOGW("%s compress voip not active, use defaults", __func__);
9176 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009177 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009178 return 0;
9179}
9180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009181static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009182 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009183 audio_devices_t devices,
9184 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009185 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309186 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009187 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009188 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009189{
9190 struct audio_device *adev = (struct audio_device *)dev;
9191 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009192 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009193 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009194 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309195 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009196 bool is_usb_dev = audio_is_usb_in_device(devices);
9197 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9198 devices,
9199 flags,
9200 source);
Andy Hung94320602018-10-29 18:31:12 -07009201 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9202 " sample_rate %u, channel_mask %#x, format %#x",
9203 __func__, flags, is_usb_dev, may_use_hifi_record,
9204 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309205
kunleizdff872d2018-08-20 14:40:33 +08009206 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009207 is_usb_dev = false;
9208 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9209 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9210 __func__, devices);
9211 }
9212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009213 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009214
9215 if (!(is_usb_dev && may_use_hifi_record)) {
9216 if (config->sample_rate == 0)
9217 config->sample_rate = 48000;
9218 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9219 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9220 if (config->format == AUDIO_FORMAT_DEFAULT)
9221 config->format = AUDIO_FORMAT_PCM_16_BIT;
9222
9223 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9224
Aalique Grahame22e49102018-12-18 14:23:57 -08009225 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9226 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009227 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309228 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009229
Rahul Sharma99770982019-03-06 17:05:26 +05309230 pthread_mutex_lock(&adev->lock);
9231 if (in_get_stream(adev, handle) != NULL) {
9232 ALOGW("%s, input stream already opened", __func__);
9233 ret = -EEXIST;
9234 }
9235 pthread_mutex_unlock(&adev->lock);
9236 if (ret)
9237 return ret;
9238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009239 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009240
9241 if (!in) {
9242 ALOGE("failed to allocate input stream");
9243 return -ENOMEM;
9244 }
9245
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309246 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309247 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9248 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009249 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009250 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009252 in->stream.common.get_sample_rate = in_get_sample_rate;
9253 in->stream.common.set_sample_rate = in_set_sample_rate;
9254 in->stream.common.get_buffer_size = in_get_buffer_size;
9255 in->stream.common.get_channels = in_get_channels;
9256 in->stream.common.get_format = in_get_format;
9257 in->stream.common.set_format = in_set_format;
9258 in->stream.common.standby = in_standby;
9259 in->stream.common.dump = in_dump;
9260 in->stream.common.set_parameters = in_set_parameters;
9261 in->stream.common.get_parameters = in_get_parameters;
9262 in->stream.common.add_audio_effect = in_add_audio_effect;
9263 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9264 in->stream.set_gain = in_set_gain;
9265 in->stream.read = in_read;
9266 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009267 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309268 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009269 in->stream.set_microphone_direction = in_set_microphone_direction;
9270 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009271 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009272
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009273 list_init(&in->device_list);
9274 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009275 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009276 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009277 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009278 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009279 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009280 in->bit_width = 16;
9281 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009282 in->direction = MIC_DIRECTION_UNSPECIFIED;
9283 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009284 list_init(&in->aec_list);
9285 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009286 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009287
Andy Hung94320602018-10-29 18:31:12 -07009288 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009289 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9290 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9291 /* Force channel config requested to mono if incall
9292 record is being requested for only uplink/downlink */
9293 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9294 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9295 ret = -EINVAL;
9296 goto err_open;
9297 }
9298 }
9299
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009300 if (is_usb_dev && may_use_hifi_record) {
9301 /* HiFi record selects an appropriate format, channel, rate combo
9302 depending on sink capabilities*/
9303 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9304 &config->format,
9305 &in->supported_formats[0],
9306 MAX_SUPPORTED_FORMATS,
9307 &config->channel_mask,
9308 &in->supported_channel_masks[0],
9309 MAX_SUPPORTED_CHANNEL_MASKS,
9310 &config->sample_rate,
9311 &in->supported_sample_rates[0],
9312 MAX_SUPPORTED_SAMPLE_RATES);
9313 if (ret != 0) {
9314 ret = -EINVAL;
9315 goto err_open;
9316 }
9317 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009318 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309319 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309320 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9321 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9322 in->config.format = PCM_FORMAT_S32_LE;
9323 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309324 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9325 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9326 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9327 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9328 bool ret_error = false;
9329 in->bit_width = 24;
9330 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9331 from HAL is 24_packed and 8_24
9332 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9333 24_packed return error indicating supported format is 24_packed
9334 *> In case of any other source requesting 24 bit or float return error
9335 indicating format supported is 16 bit only.
9336
9337 on error flinger will retry with supported format passed
9338 */
9339 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9340 (source != AUDIO_SOURCE_CAMCORDER)) {
9341 config->format = AUDIO_FORMAT_PCM_16_BIT;
9342 if (config->sample_rate > 48000)
9343 config->sample_rate = 48000;
9344 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009345 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9346 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309347 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9348 ret_error = true;
9349 }
9350
9351 if (ret_error) {
9352 ret = -EINVAL;
9353 goto err_open;
9354 }
9355 }
9356
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009357 in->channel_mask = config->channel_mask;
9358 in->format = config->format;
9359
9360 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309361
9362 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9363 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9364 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9365 else {
9366 ret = -EINVAL;
9367 goto err_open;
9368 }
9369 }
9370
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009371 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309372 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9373 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009374 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9375 is_low_latency = true;
9376#if LOW_LATENCY_CAPTURE_USE_CASE
9377 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9378#endif
9379 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009380 if (!in->realtime) {
9381 in->config = pcm_config_audio_capture;
9382 frame_size = audio_stream_in_frame_size(&in->stream);
9383 buffer_size = get_input_buffer_size(config->sample_rate,
9384 config->format,
9385 channel_count,
9386 is_low_latency);
9387 in->config.period_size = buffer_size / frame_size;
9388 in->config.rate = config->sample_rate;
9389 in->af_period_multiplier = 1;
9390 } else {
9391 // period size is left untouched for rt mode playback
9392 in->config = pcm_config_audio_capture_rt;
9393 in->af_period_multiplier = af_period_multiplier;
9394 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009395 }
9396
9397 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9398 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9399 in->realtime = 0;
9400 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9401 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009402 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009403 in->stream.start = in_start;
9404 in->stream.stop = in_stop;
9405 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9406 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009407 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009408 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009409 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9410 in->config = pcm_config_audio_capture;
9411 frame_size = audio_stream_in_frame_size(&in->stream);
9412 buffer_size = get_input_buffer_size(config->sample_rate,
9413 config->format,
9414 channel_count,
9415 false /*is_low_latency*/);
9416 in->config.period_size = buffer_size / frame_size;
9417 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009418 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009419 switch (config->format) {
9420 case AUDIO_FORMAT_PCM_32_BIT:
9421 in->bit_width = 32;
9422 break;
9423 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9424 case AUDIO_FORMAT_PCM_8_24_BIT:
9425 in->bit_width = 24;
9426 break;
9427 default:
9428 in->bit_width = 16;
9429 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009430 } else if (is_single_device_type_equal(&in->device_list,
9431 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9432 is_single_device_type_equal(&in->device_list,
9433 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009434 if (config->sample_rate == 0)
9435 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9436 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9437 config->sample_rate != 8000) {
9438 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9439 ret = -EINVAL;
9440 goto err_open;
9441 }
9442 if (config->format == AUDIO_FORMAT_DEFAULT)
9443 config->format = AUDIO_FORMAT_PCM_16_BIT;
9444 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9445 config->format = AUDIO_FORMAT_PCM_16_BIT;
9446 ret = -EINVAL;
9447 goto err_open;
9448 }
9449
9450 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009451 if (adev->ha_proxy_enable &&
9452 is_single_device_type_equal(&in->device_list,
9453 AUDIO_DEVICE_IN_TELEPHONY_RX))
9454 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009455 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009456 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009457 in->af_period_multiplier = 1;
9458 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9459 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9460 (config->sample_rate == 8000 ||
9461 config->sample_rate == 16000 ||
9462 config->sample_rate == 32000 ||
9463 config->sample_rate == 48000) &&
9464 channel_count == 1) {
9465 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9466 in->config = pcm_config_audio_capture;
9467 frame_size = audio_stream_in_frame_size(&in->stream);
9468 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9469 config->sample_rate,
9470 config->format,
9471 channel_count, false /*is_low_latency*/);
9472 in->config.period_size = buffer_size / frame_size;
9473 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9474 in->config.rate = config->sample_rate;
9475 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009476 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309477 int ret_val;
9478 pthread_mutex_lock(&adev->lock);
9479 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9480 in, config, &channel_mask_updated);
9481 pthread_mutex_unlock(&adev->lock);
9482
9483 if (!ret_val) {
9484 if (channel_mask_updated == true) {
9485 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9486 __func__, config->channel_mask);
9487 ret = -EINVAL;
9488 goto err_open;
9489 }
9490 ALOGD("%s: created multi-channel session succesfully",__func__);
9491 } else if (audio_extn_compr_cap_enabled() &&
9492 audio_extn_compr_cap_format_supported(config->format) &&
9493 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9494 audio_extn_compr_cap_init(in);
9495 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309496 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309497 if (ret)
9498 goto err_open;
9499 } else {
9500 in->config = pcm_config_audio_capture;
9501 in->config.rate = config->sample_rate;
9502 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309503 in->format = config->format;
9504 frame_size = audio_stream_in_frame_size(&in->stream);
9505 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009506 config->format,
9507 channel_count,
9508 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009509 /* prevent division-by-zero */
9510 if (frame_size == 0) {
9511 ALOGE("%s: Error frame_size==0", __func__);
9512 ret = -EINVAL;
9513 goto err_open;
9514 }
9515
Revathi Uddarajud2634032017-12-07 14:42:34 +05309516 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009517 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009518
Revathi Uddarajud2634032017-12-07 14:42:34 +05309519 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9520 /* optionally use VOIP usecase depending on config(s) */
9521 ret = adev_update_voice_comm_input_stream(in, config);
9522 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009523
Revathi Uddarajud2634032017-12-07 14:42:34 +05309524 if (ret) {
9525 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9526 goto err_open;
9527 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009528 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309529
9530 /* assign concurrent capture usecase if record has to caried out from
9531 * actual hardware input source */
9532 if (audio_extn_is_concurrent_capture_enabled() &&
9533 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309534 /* Acquire lock to avoid two concurrent use cases initialized to
9535 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009536
Samyak Jainc37062f2019-04-25 18:41:06 +05309537 if (in->usecase == USECASE_AUDIO_RECORD) {
9538 pthread_mutex_lock(&adev->lock);
9539 if (!(adev->pcm_record_uc_state)) {
9540 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9541 adev->pcm_record_uc_state = 1;
9542 pthread_mutex_unlock(&adev->lock);
9543 } else {
9544 pthread_mutex_unlock(&adev->lock);
9545 /* Assign compress record use case for second record */
9546 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9547 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9548 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9549 if (audio_extn_cin_applicable_stream(in)) {
9550 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309551 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309552 if (ret)
9553 goto err_open;
9554 }
9555 }
9556 }
kunleiz28c73e72019-03-27 17:24:04 +08009557 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009558 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309559 if (audio_extn_ssr_get_stream() != in)
9560 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009561
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009562 in->sample_rate = in->config.rate;
9563
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309564 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9565 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009566 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009567 in->sample_rate, in->bit_width,
9568 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309569 register_format(in->format, in->supported_formats);
9570 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9571 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309572
Aalique Grahame22e49102018-12-18 14:23:57 -08009573 in->error_log = error_log_create(
9574 ERROR_LOG_ENTRIES,
9575 1000000000 /* aggregate consecutive identical errors within one second */);
9576
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009577 /* This stream could be for sound trigger lab,
9578 get sound trigger pcm if present */
9579 audio_extn_sound_trigger_check_and_get_session(in);
9580
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309581 lock_input_stream(in);
9582 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9583 pthread_mutex_lock(&adev->lock);
9584 in->card_status = adev->card_status;
9585 pthread_mutex_unlock(&adev->lock);
9586 pthread_mutex_unlock(&in->lock);
9587
Aalique Grahame22e49102018-12-18 14:23:57 -08009588 stream_app_type_cfg_init(&in->app_type_cfg);
9589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009590 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009591
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009592 ret = io_streams_map_insert(adev, &in->stream.common,
9593 handle, AUDIO_PATCH_HANDLE_NONE);
9594 if (ret != 0)
9595 goto err_open;
9596
Derek Chenf939fb72018-11-13 13:34:41 -08009597 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9598 calloc(1, sizeof(streams_input_ctxt_t));
9599 if (in_ctxt == NULL) {
9600 ALOGE("%s fail to allocate input ctxt", __func__);
9601 ret = -ENOMEM;
9602 goto err_open;
9603 }
9604 in_ctxt->input = in;
9605
9606 pthread_mutex_lock(&adev->lock);
9607 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9608 pthread_mutex_unlock(&adev->lock);
9609
Eric Laurent994a6932013-07-17 11:51:42 -07009610 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009611 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009612
9613err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309614 if (in->usecase == USECASE_AUDIO_RECORD) {
9615 pthread_mutex_lock(&adev->lock);
9616 adev->pcm_record_uc_state = 0;
9617 pthread_mutex_unlock(&adev->lock);
9618 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009619 free(in);
9620 *stream_in = NULL;
9621 return ret;
9622}
9623
9624static void adev_close_input_stream(struct audio_hw_device *dev,
9625 struct audio_stream_in *stream)
9626{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009627 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009628 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009629 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309630
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309631 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009632
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009633 if (in == NULL) {
9634 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9635 return;
9636 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009637 io_streams_map_remove(adev, in->capture_handle);
9638
kunleiz70e57612018-12-28 17:50:23 +08009639 /* must deregister from sndmonitor first to prevent races
9640 * between the callback and close_stream
9641 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309642 audio_extn_snd_mon_unregister_listener(stream);
9643
kunleiz70e57612018-12-28 17:50:23 +08009644 /* Disable echo reference if there are no active input, hfp call
9645 * and sound trigger while closing input stream
9646 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009647 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009648 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009649 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9650 struct listnode out_devices;
9651 list_init(&out_devices);
9652 platform_set_echo_reference(adev, false, &out_devices);
9653 } else
kunleiz70e57612018-12-28 17:50:23 +08009654 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309655
Weiyin Jiang2995f662019-04-17 14:25:12 +08009656 error_log_destroy(in->error_log);
9657 in->error_log = NULL;
9658
Pallavid7c7a272018-01-16 11:22:55 +05309659
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009660 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309661 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009662 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309663 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009664 if (ret != 0)
9665 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9666 __func__, ret);
9667 } else
9668 in_standby(&stream->common);
9669
Revathi Uddarajud2634032017-12-07 14:42:34 +05309670 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309671 if (in->usecase == USECASE_AUDIO_RECORD) {
9672 adev->pcm_record_uc_state = 0;
9673 }
9674
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009675 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9676 adev->enable_voicerx = false;
9677 }
9678
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009679 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009680 audio_extn_ssr_deinit();
9681 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009682
Garmond Leunge2433c32017-09-28 21:51:22 -07009683 if (audio_extn_ffv_get_stream() == in) {
9684 audio_extn_ffv_stream_deinit();
9685 }
9686
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309687 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009688 audio_extn_compr_cap_format_supported(in->config.format))
9689 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309690
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309691 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309692 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009693
Mingming Yinfd7607b2016-01-22 12:48:44 -08009694 if (in->is_st_session) {
9695 ALOGV("%s: sound trigger pcm stop lab", __func__);
9696 audio_extn_sound_trigger_stop_lab(in);
9697 }
Derek Chenf939fb72018-11-13 13:34:41 -08009698 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9699 if (in_ctxt != NULL) {
9700 list_remove(&in_ctxt->list);
9701 free(in_ctxt);
9702 } else {
9703 ALOGW("%s, input stream already closed", __func__);
9704 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009705 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309706 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009707 return;
9708}
9709
Aalique Grahame22e49102018-12-18 14:23:57 -08009710/* verifies input and output devices and their capabilities.
9711 *
9712 * This verification is required when enabling extended bit-depth or
9713 * sampling rates, as not all qcom products support it.
9714 *
9715 * Suitable for calling only on initialization such as adev_open().
9716 * It fills the audio_device use_case_table[] array.
9717 *
9718 * Has a side-effect that it needs to configure audio routing / devices
9719 * in order to power up the devices and read the device parameters.
9720 * It does not acquire any hw device lock. Should restore the devices
9721 * back to "normal state" upon completion.
9722 */
9723static int adev_verify_devices(struct audio_device *adev)
9724{
9725 /* enumeration is a bit difficult because one really wants to pull
9726 * the use_case, device id, etc from the hidden pcm_device_table[].
9727 * In this case there are the following use cases and device ids.
9728 *
9729 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9730 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9731 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9732 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9733 * [USECASE_AUDIO_RECORD] = {0, 0},
9734 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9735 * [USECASE_VOICE_CALL] = {2, 2},
9736 *
9737 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9738 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9739 */
9740
9741 /* should be the usecases enabled in adev_open_input_stream() */
9742 static const int test_in_usecases[] = {
9743 USECASE_AUDIO_RECORD,
9744 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9745 };
9746 /* should be the usecases enabled in adev_open_output_stream()*/
9747 static const int test_out_usecases[] = {
9748 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9749 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9750 };
9751 static const usecase_type_t usecase_type_by_dir[] = {
9752 PCM_PLAYBACK,
9753 PCM_CAPTURE,
9754 };
9755 static const unsigned flags_by_dir[] = {
9756 PCM_OUT,
9757 PCM_IN,
9758 };
9759
9760 size_t i;
9761 unsigned dir;
9762 const unsigned card_id = adev->snd_card;
9763
9764 for (dir = 0; dir < 2; ++dir) {
9765 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9766 const unsigned flags_dir = flags_by_dir[dir];
9767 const size_t testsize =
9768 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9769 const int *testcases =
9770 dir ? test_in_usecases : test_out_usecases;
9771 const audio_devices_t audio_device =
9772 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9773
9774 for (i = 0; i < testsize; ++i) {
9775 const audio_usecase_t audio_usecase = testcases[i];
9776 int device_id;
9777 struct pcm_params **pparams;
9778 struct stream_out out;
9779 struct stream_in in;
9780 struct audio_usecase uc_info;
9781 int retval;
9782
9783 pparams = &adev->use_case_table[audio_usecase];
9784 pcm_params_free(*pparams); /* can accept null input */
9785 *pparams = NULL;
9786
9787 /* find the device ID for the use case (signed, for error) */
9788 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9789 if (device_id < 0)
9790 continue;
9791
9792 /* prepare structures for device probing */
9793 memset(&uc_info, 0, sizeof(uc_info));
9794 uc_info.id = audio_usecase;
9795 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009796 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009797 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009798 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009799 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009800 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009801 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9802 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009803 }
9804 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009805 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009806 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009807 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009808 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009809 uc_info.in_snd_device = SND_DEVICE_NONE;
9810 uc_info.out_snd_device = SND_DEVICE_NONE;
9811 list_add_tail(&adev->usecase_list, &uc_info.list);
9812
9813 /* select device - similar to start_(in/out)put_stream() */
9814 retval = select_devices(adev, audio_usecase);
9815 if (retval >= 0) {
9816 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9817#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009818 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009819 if (*pparams) {
9820 ALOGV("%s: (%s) card %d device %d", __func__,
9821 dir ? "input" : "output", card_id, device_id);
9822 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9823 } else {
9824 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9825 }
9826#endif
9827 }
9828
9829 /* deselect device - similar to stop_(in/out)put_stream() */
9830 /* 1. Get and set stream specific mixer controls */
9831 retval = disable_audio_route(adev, &uc_info);
9832 /* 2. Disable the rx device */
9833 retval = disable_snd_device(adev,
9834 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9835 list_remove(&uc_info.list);
9836 }
9837 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009838 return 0;
9839}
9840
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009841int update_patch(unsigned int num_sources,
9842 const struct audio_port_config *sources,
9843 unsigned int num_sinks,
9844 const struct audio_port_config *sinks,
9845 audio_patch_handle_t handle,
9846 struct audio_patch_info *p_info,
9847 patch_type_t patch_type, bool new_patch)
9848{
9849 ALOGD("%s: enter", __func__);
9850
9851 if (p_info == NULL) {
9852 ALOGE("%s: Invalid patch pointer", __func__);
9853 return -EINVAL;
9854 }
9855
9856 if (new_patch) {
9857 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9858 if (p_info->patch == NULL) {
9859 ALOGE("%s: Could not allocate patch", __func__);
9860 return -ENOMEM;
9861 }
9862 }
9863
9864 p_info->patch->id = handle;
9865 p_info->patch->num_sources = num_sources;
9866 p_info->patch->num_sinks = num_sinks;
9867
9868 for (int i = 0; i < num_sources; i++)
9869 p_info->patch->sources[i] = sources[i];
9870 for (int i = 0; i < num_sinks; i++)
9871 p_info->patch->sinks[i] = sinks[i];
9872
9873 p_info->patch_type = patch_type;
9874 return 0;
9875}
9876
9877audio_patch_handle_t generate_patch_handle()
9878{
9879 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9880 if (++patch_handle < 0)
9881 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9882 return patch_handle;
9883}
9884
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309885int adev_create_audio_patch(struct audio_hw_device *dev,
9886 unsigned int num_sources,
9887 const struct audio_port_config *sources,
9888 unsigned int num_sinks,
9889 const struct audio_port_config *sinks,
9890 audio_patch_handle_t *handle)
9891{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009892 int ret = 0;
9893 struct audio_device *adev = (struct audio_device *)dev;
9894 struct audio_patch_info *p_info = NULL;
9895 patch_type_t patch_type = PATCH_NONE;
9896 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9897 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9898 struct audio_stream_info *s_info = NULL;
9899 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009900 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009901 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9902 bool new_patch = false;
9903 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309904
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009905 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9906 num_sources, num_sinks, *handle);
9907
9908 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9909 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9910 ALOGE("%s: Invalid patch arguments", __func__);
9911 ret = -EINVAL;
9912 goto done;
9913 }
9914
9915 if (num_sources > 1) {
9916 ALOGE("%s: Multiple sources are not supported", __func__);
9917 ret = -EINVAL;
9918 goto done;
9919 }
9920
9921 if (sources == NULL || sinks == NULL) {
9922 ALOGE("%s: Invalid sources or sinks port config", __func__);
9923 ret = -EINVAL;
9924 goto done;
9925 }
9926
9927 ALOGV("%s: source role %d, source type %d", __func__,
9928 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009929 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009930
9931 // Populate source/sink information and fetch stream info
9932 switch (sources[0].type) {
9933 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9934 device_type = sources[0].ext.device.type;
9935 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009936 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009937 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9938 patch_type = PATCH_CAPTURE;
9939 io_handle = sinks[0].ext.mix.handle;
9940 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009941 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009942 __func__, device_type, io_handle);
9943 } else {
9944 // Device to device patch is not implemented.
9945 // This space will need changes if audio HAL
9946 // handles device to device patches in the future.
9947 patch_type = PATCH_DEVICE_LOOPBACK;
9948 }
9949 break;
9950 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9951 io_handle = sources[0].ext.mix.handle;
9952 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009953 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009954 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009955 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009956 }
9957 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009958 ALOGD("%s: Playback patch from mix handle %d to device %x",
9959 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009960 break;
9961 case AUDIO_PORT_TYPE_SESSION:
9962 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009963 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9964 ret = -EINVAL;
9965 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009966 }
9967
9968 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009969
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009970 // Generate patch info and update patch
9971 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009972 *handle = generate_patch_handle();
9973 p_info = (struct audio_patch_info *)
9974 calloc(1, sizeof(struct audio_patch_info));
9975 if (p_info == NULL) {
9976 ALOGE("%s: Failed to allocate memory", __func__);
9977 pthread_mutex_unlock(&adev->lock);
9978 ret = -ENOMEM;
9979 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009980 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009981 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009982 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009983 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009984 if (p_info == NULL) {
9985 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9986 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009987 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009988 ret = -EINVAL;
9989 goto done;
9990 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009991 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009992 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009993 *handle, p_info, patch_type, new_patch);
9994
9995 // Fetch stream info of associated mix for playback or capture patches
9996 if (p_info->patch_type == PATCH_PLAYBACK ||
9997 p_info->patch_type == PATCH_CAPTURE) {
9998 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9999 if (s_info == NULL) {
10000 ALOGE("%s: Failed to obtain stream info", __func__);
10001 if (new_patch)
10002 free(p_info);
10003 pthread_mutex_unlock(&adev->lock);
10004 ret = -EINVAL;
10005 goto done;
10006 }
10007 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10008 s_info->patch_handle = *handle;
10009 stream = s_info->stream;
10010 }
10011 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010012
10013 // Update routing for stream
10014 if (stream != NULL) {
10015 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010016 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010017 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010018 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010019 if (ret < 0) {
10020 pthread_mutex_lock(&adev->lock);
10021 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10022 if (new_patch)
10023 free(p_info);
10024 pthread_mutex_unlock(&adev->lock);
10025 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10026 goto done;
10027 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010028 }
10029
10030 // Add new patch to patch map
10031 if (!ret && new_patch) {
10032 pthread_mutex_lock(&adev->lock);
10033 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010034 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010035 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010036 }
10037
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010038done:
10039 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010040 num_sources,
10041 sources,
10042 num_sinks,
10043 sinks,
10044 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010045 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010046 num_sources,
10047 sources,
10048 num_sinks,
10049 sinks,
10050 handle);
10051 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010052}
10053
10054int adev_release_audio_patch(struct audio_hw_device *dev,
10055 audio_patch_handle_t handle)
10056{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010057 struct audio_device *adev = (struct audio_device *) dev;
10058 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010059 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010060 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010061
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010062 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10063 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10064 ret = -EINVAL;
10065 goto done;
10066 }
10067
10068 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010069 pthread_mutex_lock(&adev->lock);
10070 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010071 if (p_info == NULL) {
10072 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010073 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010074 ret = -EINVAL;
10075 goto done;
10076 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010077 struct audio_patch *patch = p_info->patch;
10078 if (patch == NULL) {
10079 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010080 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010081 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010082 goto done;
10083 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010084 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10085 switch (patch->sources[0].type) {
10086 case AUDIO_PORT_TYPE_MIX:
10087 io_handle = patch->sources[0].ext.mix.handle;
10088 break;
10089 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010090 if (p_info->patch_type == PATCH_CAPTURE)
10091 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010092 break;
10093 case AUDIO_PORT_TYPE_SESSION:
10094 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010095 pthread_mutex_unlock(&adev->lock);
10096 ret = -EINVAL;
10097 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010098 }
10099
10100 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010101 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010102 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010103 if (patch_type == PATCH_PLAYBACK ||
10104 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010105 struct audio_stream_info *s_info =
10106 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10107 if (s_info == NULL) {
10108 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10109 pthread_mutex_unlock(&adev->lock);
10110 goto done;
10111 }
10112 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10113 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010114 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010115 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010116
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010117 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010118 struct listnode devices;
10119 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010120 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010121 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010122 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010123 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010124 }
10125
10126 if (ret < 0)
10127 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10128
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010129done:
10130 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10131 audio_extn_auto_hal_release_audio_patch(dev, handle);
10132
10133 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010134 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010135}
10136
10137int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10138{
Derek Chenf13dd492018-11-13 14:53:51 -080010139 int ret = 0;
10140
10141 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10142 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10143 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010144}
10145
10146int adev_set_audio_port_config(struct audio_hw_device *dev,
10147 const struct audio_port_config *config)
10148{
Derek Chenf13dd492018-11-13 14:53:51 -080010149 int ret = 0;
10150
10151 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10152 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10153 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010154}
10155
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010156static int adev_dump(const audio_hw_device_t *device __unused,
10157 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010158{
10159 return 0;
10160}
10161
10162static int adev_close(hw_device_t *device)
10163{
Aalique Grahame22e49102018-12-18 14:23:57 -080010164 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010165 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010166
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010167 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010168 return 0;
10169
10170 pthread_mutex_lock(&adev_init_lock);
10171
10172 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010173 if (audio_extn_spkr_prot_is_enabled())
10174 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010175 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010176 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010177 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010178 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010179 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010180 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010181 audio_extn_utils_release_streams_cfg_lists(
10182 &adev->streams_output_cfg_list,
10183 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010184 if (audio_extn_qap_is_enabled())
10185 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010186 if (audio_extn_qaf_is_enabled())
10187 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010188 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010189 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010190 free(adev->snd_dev_ref_cnt);
10191 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010192 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10193 pcm_params_free(adev->use_case_table[i]);
10194 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010195 if (adev->adm_deinit)
10196 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010197 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010198 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010199 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010200 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010201 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010202 if (adev->device_cfg_params) {
10203 free(adev->device_cfg_params);
10204 adev->device_cfg_params = NULL;
10205 }
Derek Chend2530072014-11-24 12:39:14 -080010206 if(adev->ext_hw_plugin)
10207 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010208 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010209 free_map(adev->patch_map);
10210 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010211 free(device);
10212 adev = NULL;
10213 }
10214 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010215 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010216 return 0;
10217}
10218
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010219/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10220 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10221 * just that it _might_ work.
10222 */
10223static int period_size_is_plausible_for_low_latency(int period_size)
10224{
10225 switch (period_size) {
10226 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010227 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010228 case 240:
10229 case 320:
10230 case 480:
10231 return 1;
10232 default:
10233 return 0;
10234 }
10235}
10236
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010237static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10238{
10239 bool is_snd_card_status = false;
10240 bool is_ext_device_status = false;
10241 char value[32];
10242 int card = -1;
10243 card_status_t status;
10244
10245 if (cookie != adev || !parms)
10246 return;
10247
10248 if (!parse_snd_card_status(parms, &card, &status)) {
10249 is_snd_card_status = true;
10250 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10251 is_ext_device_status = true;
10252 } else {
10253 // not a valid event
10254 return;
10255 }
10256
10257 pthread_mutex_lock(&adev->lock);
10258 if (card == adev->snd_card || is_ext_device_status) {
10259 if (is_snd_card_status && adev->card_status != status) {
10260 adev->card_status = status;
10261 platform_snd_card_update(adev->platform, status);
10262 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010263 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010264 if (status == CARD_STATUS_OFFLINE)
10265 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010266 } else if (is_ext_device_status) {
10267 platform_set_parameters(adev->platform, parms);
10268 }
10269 }
10270 pthread_mutex_unlock(&adev->lock);
10271 return;
10272}
10273
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010274/* out and adev lock held */
10275static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10276{
10277 struct audio_usecase *uc_info;
10278 float left_p;
10279 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010280 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010281
10282 uc_info = get_usecase_from_list(adev, out->usecase);
10283 if (uc_info == NULL) {
10284 ALOGE("%s: Could not find the usecase (%d) in the list",
10285 __func__, out->usecase);
10286 return -EINVAL;
10287 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010288 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010289
10290 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10291 out->usecase, use_case_table[out->usecase]);
10292
10293 if (restore) {
10294 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010295 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010296 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010297 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10298 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010299 pthread_mutex_lock(&out->compr_mute_lock);
10300 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010301 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010302 out->a2dp_compress_mute = false;
10303 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10304 }
10305 pthread_mutex_unlock(&out->compr_mute_lock);
10306 }
10307 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010308 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10309 // mute compress stream if suspended
10310 pthread_mutex_lock(&out->compr_mute_lock);
10311 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010312 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010313 assign_devices(&devices, &out->device_list);
10314 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010315 left_p = out->volume_l;
10316 right_p = out->volume_r;
10317 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10318 compress_pause(out->compr);
10319 out_set_compr_volume(&out->stream, (float)0, (float)0);
10320 out->a2dp_compress_mute = true;
10321 select_devices(adev, out->usecase);
10322 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10323 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010324 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010325 out->volume_l = left_p;
10326 out->volume_r = right_p;
10327 }
Zhou Songc576a452019-09-09 14:17:40 +080010328 pthread_mutex_unlock(&out->compr_mute_lock);
10329 } else {
10330 // tear down a2dp path for non offloaded streams
10331 if (audio_extn_a2dp_source_is_suspended())
10332 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010333 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010334 }
10335 ALOGV("%s: exit", __func__);
10336 return 0;
10337}
10338
10339int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10340{
10341 int ret = 0;
10342
10343 lock_output_stream(out);
10344 pthread_mutex_lock(&adev->lock);
10345
10346 ret = check_a2dp_restore_l(adev, out, restore);
10347
10348 pthread_mutex_unlock(&adev->lock);
10349 pthread_mutex_unlock(&out->lock);
10350 return ret;
10351}
10352
Haynes Mathew George01156f92018-04-13 15:29:54 -070010353void adev_on_battery_status_changed(bool charging)
10354{
10355 pthread_mutex_lock(&adev->lock);
10356 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10357 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010358 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010359 pthread_mutex_unlock(&adev->lock);
10360}
10361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010362static int adev_open(const hw_module_t *module, const char *name,
10363 hw_device_t **device)
10364{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010365 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010366 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010367 char mixer_ctl_name[128] = {0};
10368 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010369
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010370 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010371 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10372
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010373 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010374 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010375 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010376 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010377 ALOGD("%s: returning existing instance of adev", __func__);
10378 ALOGD("%s: exit", __func__);
10379 pthread_mutex_unlock(&adev_init_lock);
10380 return 0;
10381 }
10382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010383 adev = calloc(1, sizeof(struct audio_device));
10384
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010385 if (!adev) {
10386 pthread_mutex_unlock(&adev_init_lock);
10387 return -ENOMEM;
10388 }
10389
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010390 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10391
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010392 // register audio ext hidl at the earliest
10393 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010394#ifdef DYNAMIC_LOG_ENABLED
10395 register_for_dynamic_logging("hal");
10396#endif
10397
Derek Chenf939fb72018-11-13 13:34:41 -080010398 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010399 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010400 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10401 maj_version = atoi(value);
10402
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010403 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010404 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010405 adev->device.common.module = (struct hw_module_t *)module;
10406 adev->device.common.close = adev_close;
10407
10408 adev->device.init_check = adev_init_check;
10409 adev->device.set_voice_volume = adev_set_voice_volume;
10410 adev->device.set_master_volume = adev_set_master_volume;
10411 adev->device.get_master_volume = adev_get_master_volume;
10412 adev->device.set_master_mute = adev_set_master_mute;
10413 adev->device.get_master_mute = adev_get_master_mute;
10414 adev->device.set_mode = adev_set_mode;
10415 adev->device.set_mic_mute = adev_set_mic_mute;
10416 adev->device.get_mic_mute = adev_get_mic_mute;
10417 adev->device.set_parameters = adev_set_parameters;
10418 adev->device.get_parameters = adev_get_parameters;
10419 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10420 adev->device.open_output_stream = adev_open_output_stream;
10421 adev->device.close_output_stream = adev_close_output_stream;
10422 adev->device.open_input_stream = adev_open_input_stream;
10423 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010424 adev->device.create_audio_patch = adev_create_audio_patch;
10425 adev->device.release_audio_patch = adev_release_audio_patch;
10426 adev->device.get_audio_port = adev_get_audio_port;
10427 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010428 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010429 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010430
10431 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010432 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010433 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010434 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010435 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010436 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010437 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010438 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010439 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010440 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010441 /* Init audio and voice feature */
10442 audio_extn_feature_init();
10443 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010444 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010445 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010446 list_init(&adev->active_inputs_list);
10447 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010448 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010449 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10450 audio_extn_utils_hash_eq);
10451 if (!adev->io_streams_map) {
10452 ALOGE("%s: Could not create io streams map", __func__);
10453 ret = -ENOMEM;
10454 goto adev_open_err;
10455 }
10456 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10457 audio_extn_utils_hash_eq);
10458 if (!adev->patch_map) {
10459 ALOGE("%s: Could not create audio patch map", __func__);
10460 ret = -ENOMEM;
10461 goto adev_open_err;
10462 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010463 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010464 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010465 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010466 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010467 adev->perf_lock_opts[0] = 0x101;
10468 adev->perf_lock_opts[1] = 0x20E;
10469 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010470 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010471 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010472 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010473 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010474
Zhou Song68ebc352019-12-05 17:11:15 +080010475 audio_extn_perf_lock_init();
10476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010477 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010478 adev->platform = platform_init(adev);
10479 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010480 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010481 ret = -EINVAL;
10482 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010483 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010484
Aalique Grahame22e49102018-12-18 14:23:57 -080010485 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010486 if (audio_extn_qap_is_enabled()) {
10487 ret = audio_extn_qap_init(adev);
10488 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010489 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010490 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010491 }
10492 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10493 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10494 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010495
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010496 if (audio_extn_qaf_is_enabled()) {
10497 ret = audio_extn_qaf_init(adev);
10498 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010499 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010500 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010501 }
10502
10503 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10504 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10505 }
10506
Derek Chenae7b0342019-02-08 15:17:04 -080010507 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010508 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10509
Eric Laurentc4aef752013-09-12 17:45:53 -070010510 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10511 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10512 if (adev->visualizer_lib == NULL) {
10513 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10514 } else {
10515 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10516 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010517 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010518 "visualizer_hal_start_output");
10519 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010520 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010521 "visualizer_hal_stop_output");
10522 }
10523 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010524 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010525 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010526 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010527 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010528 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010529 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010530
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010531 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10532 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10533 if (adev->offload_effects_lib == NULL) {
10534 ALOGE("%s: DLOPEN failed for %s", __func__,
10535 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10536 } else {
10537 ALOGV("%s: DLOPEN successful for %s", __func__,
10538 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10539 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010540 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010541 "offload_effects_bundle_hal_start_output");
10542 adev->offload_effects_stop_output =
10543 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10544 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010545 adev->offload_effects_set_hpx_state =
10546 (int (*)(bool))dlsym(adev->offload_effects_lib,
10547 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010548 adev->offload_effects_get_parameters =
10549 (void (*)(struct str_parms *, struct str_parms *))
10550 dlsym(adev->offload_effects_lib,
10551 "offload_effects_bundle_get_parameters");
10552 adev->offload_effects_set_parameters =
10553 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10554 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010555 }
10556 }
10557
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010558 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10559 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10560 if (adev->adm_lib == NULL) {
10561 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10562 } else {
10563 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10564 adev->adm_init = (adm_init_t)
10565 dlsym(adev->adm_lib, "adm_init");
10566 adev->adm_deinit = (adm_deinit_t)
10567 dlsym(adev->adm_lib, "adm_deinit");
10568 adev->adm_register_input_stream = (adm_register_input_stream_t)
10569 dlsym(adev->adm_lib, "adm_register_input_stream");
10570 adev->adm_register_output_stream = (adm_register_output_stream_t)
10571 dlsym(adev->adm_lib, "adm_register_output_stream");
10572 adev->adm_deregister_stream = (adm_deregister_stream_t)
10573 dlsym(adev->adm_lib, "adm_deregister_stream");
10574 adev->adm_request_focus = (adm_request_focus_t)
10575 dlsym(adev->adm_lib, "adm_request_focus");
10576 adev->adm_abandon_focus = (adm_abandon_focus_t)
10577 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010578 adev->adm_set_config = (adm_set_config_t)
10579 dlsym(adev->adm_lib, "adm_set_config");
10580 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10581 dlsym(adev->adm_lib, "adm_request_focus_v2");
10582 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10583 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10584 adev->adm_on_routing_change = (adm_on_routing_change_t)
10585 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010586 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10587 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010588 }
10589 }
10590
Aalique Grahame22e49102018-12-18 14:23:57 -080010591 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010592 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010593 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010594 //initialize this to false for now,
10595 //this will be set to true through set param
10596 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010597
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010598 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010599 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010600
10601 if (k_enable_extended_precision)
10602 adev_verify_devices(adev);
10603
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010604 adev->dsp_bit_width_enforce_mode =
10605 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010606
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010607 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10608 &adev->streams_output_cfg_list,
10609 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010610
Kiran Kandi910e1862013-10-29 13:29:42 -070010611 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010612
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010613 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010614 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010615 trial = atoi(value);
10616 if (period_size_is_plausible_for_low_latency(trial)) {
10617 pcm_config_low_latency.period_size = trial;
10618 pcm_config_low_latency.start_threshold = trial / 4;
10619 pcm_config_low_latency.avail_min = trial / 4;
10620 configured_low_latency_capture_period_size = trial;
10621 }
10622 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010623 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10624 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010625 trial = atoi(value);
10626 if (period_size_is_plausible_for_low_latency(trial)) {
10627 configured_low_latency_capture_period_size = trial;
10628 }
10629 }
10630
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010631 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10632
Eric Laurent4b084132018-10-19 17:33:43 -070010633 adev->camera_orientation = CAMERA_DEFAULT;
10634
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010635 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010636 af_period_multiplier = atoi(value);
10637 if (af_period_multiplier < 0)
10638 af_period_multiplier = 2;
10639 else if (af_period_multiplier > 4)
10640 af_period_multiplier = 4;
10641
10642 ALOGV("new period_multiplier = %d", af_period_multiplier);
10643 }
10644
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010645 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010646
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010647 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010648 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010649 pthread_mutex_unlock(&adev_init_lock);
10650
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010651 if (adev->adm_init)
10652 adev->adm_data = adev->adm_init();
10653
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010654 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010655 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010656
10657 audio_extn_snd_mon_init();
10658 pthread_mutex_lock(&adev->lock);
10659 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10660 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010661 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10662 /*
10663 * if the battery state callback happens before charging can be queried,
10664 * it will be guarded with the adev->lock held in the cb function and so
10665 * the callback value will reflect the latest state
10666 */
10667 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010668 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010669 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010670 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010671 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010672 /* Allocate memory for Device config params */
10673 adev->device_cfg_params = (struct audio_device_config_param*)
10674 calloc(platform_get_max_codec_backend(),
10675 sizeof(struct audio_device_config_param));
10676 if (adev->device_cfg_params == NULL)
10677 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010678
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010679 /*
10680 * Check if new PSPD matrix mixer control is supported. If not
10681 * supported, then set flag so that old mixer ctrl is sent while
10682 * sending pspd coefficients on older kernel version. Query mixer
10683 * control for default pcm id and channel value one.
10684 */
10685 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10686 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10687
10688 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10689 if (!ctl) {
10690 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10691 __func__, mixer_ctl_name);
10692 adev->use_old_pspd_mix_ctrl = true;
10693 }
10694
Eric Laurent994a6932013-07-17 11:51:42 -070010695 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010696 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010697
10698adev_open_err:
10699 free_map(adev->patch_map);
10700 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010701 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010702 pthread_mutex_destroy(&adev->lock);
10703 free(adev);
10704 adev = NULL;
10705 *device = NULL;
10706 pthread_mutex_unlock(&adev_init_lock);
10707 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010708}
10709
10710static struct hw_module_methods_t hal_module_methods = {
10711 .open = adev_open,
10712};
10713
10714struct audio_module HAL_MODULE_INFO_SYM = {
10715 .common = {
10716 .tag = HARDWARE_MODULE_TAG,
10717 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10718 .hal_api_version = HARDWARE_HAL_API_VERSION,
10719 .id = AUDIO_HARDWARE_MODULE_ID,
10720 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010721 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010722 .methods = &hal_module_methods,
10723 },
10724};