blob: 8aaab925f5f9a0efcef2b7670e9b8df59cf87309 [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
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301636
1637case 9
1638 uc->dev d1 (a1), d2(a2) B1 B2
1639 new_uc->dev d1 (a1), d22 (a2) B1, B2
1640 resolution: disable enable uc-dev on d2 since backends match
1641 we cannot enable two streams on two different devices if they
1642 share the same backend. This is special case for combo use case
1643 with a2dp and sco devices which uses same backend.
1644 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001645*/
1646static snd_device_t derive_playback_snd_device(void * platform,
1647 struct audio_usecase *uc,
1648 struct audio_usecase *new_uc,
1649 snd_device_t new_snd_device)
1650{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001651 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001652
1653 snd_device_t d1 = uc->out_snd_device;
1654 snd_device_t d2 = new_snd_device;
1655
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001656 list_init(&a1);
1657 list_init(&a2);
1658
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301659 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301660 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001661 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1662 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301663 break;
1664 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001665 assign_devices(&a1, &uc->stream.out->device_list);
1666 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301667 break;
1668 }
1669
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001670 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001671 if (!compare_devices(&a1, &a2) &&
1672 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001673 snd_device_t d3[2];
1674 int num_devices = 0;
1675 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001676 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001677 &num_devices,
1678 d3);
1679 if (ret < 0) {
1680 if (ret != -ENOSYS) {
1681 ALOGW("%s failed to split snd_device %d",
1682 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001683 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001684 }
1685 goto end;
1686 }
1687
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001688 if (platform_check_backends_match(d3[0], d3[1])) {
1689 return d2; // case 5
1690 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301691 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1692 platform_check_backends_match(d1, d2))
1693 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001694 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301695 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001696 // check if d1 is related to any of d3's
1697 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001698 return d1; // case 1
1699 else
1700 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001701 }
1702 } else {
1703 if (platform_check_backends_match(d1, d2)) {
1704 return d2; // case 2, 4
1705 } else {
1706 return d1; // case 6, 3
1707 }
1708 }
1709
1710end:
1711 return d2; // return whatever was calculated before.
1712}
1713
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001714static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301715 struct audio_usecase *uc_info,
1716 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001717{
1718 struct listnode *node;
1719 struct audio_usecase *usecase;
1720 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301721 snd_device_t uc_derive_snd_device;
1722 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001723 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1724 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001725 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301726 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001727 /*
1728 * This function is to make sure that all the usecases that are active on
1729 * the hardware codec backend are always routed to any one device that is
1730 * handled by the hardware codec.
1731 * For example, if low-latency and deep-buffer usecases are currently active
1732 * on speaker and out_set_parameters(headset) is received on low-latency
1733 * output, then we have to make sure deep-buffer is also switched to headset,
1734 * because of the limitation that both the devices cannot be enabled
1735 * at the same time as they share the same backend.
1736 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001737 /*
1738 * This call is to check if we need to force routing for a particular stream
1739 * If there is a backend configuration change for the device when a
1740 * new stream starts, then ADM needs to be closed and re-opened with the new
1741 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001742 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001743 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001744 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1745 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301746 /* For a2dp device reconfigure all active sessions
1747 * with new AFE encoder format based on a2dp state
1748 */
1749 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301750 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1751 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301752 audio_extn_a2dp_is_force_device_switch()) {
1753 force_routing = true;
1754 force_restart_session = true;
1755 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001756
1757 /*
1758 * Island cfg and power mode config needs to set before AFE port start.
1759 * Set force routing in case of voice device was enable before.
1760 */
1761 if (uc_info->type == VOICE_CALL &&
1762 voice_extn_is_voice_power_mode_supported() &&
1763 platform_check_and_update_island_power_status(adev->platform,
1764 uc_info,
1765 snd_device)) {
1766 force_routing = true;
1767 ALOGD("%s:becf: force routing %d for power mode supported device",
1768 __func__, force_routing);
1769 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301770 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1771
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001772 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001773 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001774 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001775 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1776 switch_device[i] = false;
1777
1778 list_for_each(node, &adev->usecase_list) {
1779 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001780
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301781 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1782 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301783 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301784 platform_get_snd_device_name(usecase->out_snd_device),
1785 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301786 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1787 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301788 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1789 usecase, uc_info, snd_device);
1790 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001791 (is_codec_backend_out_device_type(&usecase->device_list) ||
1792 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1793 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1794 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1795 is_a2dp_out_device_type(&usecase->device_list) ||
1796 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301797 ((force_restart_session) ||
1798 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301799 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1800 __func__, use_case_table[usecase->id],
1801 platform_get_snd_device_name(usecase->out_snd_device));
1802 disable_audio_route(adev, usecase);
1803 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301804 /* Enable existing usecase on derived playback device */
1805 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301806 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301807 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001808 }
1809 }
1810
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301811 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1812 num_uc_to_switch);
1813
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001814 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001815 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001816
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301817 /* Make sure the previous devices to be disabled first and then enable the
1818 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001819 list_for_each(node, &adev->usecase_list) {
1820 usecase = node_to_item(node, struct audio_usecase, list);
1821 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001822 /* Check if output sound device to be switched can be split and if any
1823 of the split devices match with derived sound device */
1824 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1825 &num_devices, split_snd_devices) == 0) {
1826 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1827 for (i = 0; i < num_devices; i++) {
1828 /* Disable devices that do not match with derived sound device */
1829 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1830 disable_snd_device(adev, split_snd_devices[i]);
1831 }
1832 } else {
1833 disable_snd_device(adev, usecase->out_snd_device);
1834 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001835 }
1836 }
1837
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001838 list_for_each(node, &adev->usecase_list) {
1839 usecase = node_to_item(node, struct audio_usecase, list);
1840 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001841 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1842 &num_devices, split_snd_devices) == 0) {
1843 /* Enable derived sound device only if it does not match with
1844 one of the split sound devices. This is because the matching
1845 sound device was not disabled */
1846 bool should_enable = true;
1847 for (i = 0; i < num_devices; i++) {
1848 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1849 should_enable = false;
1850 break;
1851 }
1852 }
1853 if (should_enable)
1854 enable_snd_device(adev, derive_snd_device[usecase->id]);
1855 } else {
1856 enable_snd_device(adev, derive_snd_device[usecase->id]);
1857 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001858 }
1859 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001860
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001861 /* Re-route all the usecases on the shared backend other than the
1862 specified usecase to new snd devices */
1863 list_for_each(node, &adev->usecase_list) {
1864 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301865 /* Update the out_snd_device only before enabling the audio route */
1866 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301867 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301868 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301869 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301870 use_case_table[usecase->id],
1871 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001872 /* Update voc calibration before enabling VoIP route */
1873 if (usecase->type == VOIP_CALL)
1874 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001875 usecase->out_snd_device,
1876 platform_get_input_snd_device(
1877 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301878 &uc_info->device_list,
1879 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301880 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301881 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001882 out_set_voip_volume(&usecase->stream.out->stream,
1883 usecase->stream.out->volume_l,
1884 usecase->stream.out->volume_r);
1885 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301886 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001887 }
1888 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001889 }
1890}
1891
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301892static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001893 struct audio_usecase *uc_info,
1894 snd_device_t snd_device)
1895{
1896 struct listnode *node;
1897 struct audio_usecase *usecase;
1898 bool switch_device[AUDIO_USECASE_MAX];
1899 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001900 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001901 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001902
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301903 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1904 snd_device);
1905 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301906
1907 /*
1908 * Make sure out devices is checked against out codec backend device and
1909 * also in devices against in codec backend. Checking out device against in
1910 * codec backend or vice versa causes issues.
1911 */
1912 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001913 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001914
1915 /*
1916 * Island cfg and power mode config needs to set before AFE port start.
1917 * Set force routing in case of voice device was enable before.
1918 */
1919
1920 if (uc_info->type == VOICE_CALL &&
1921 voice_extn_is_voice_power_mode_supported() &&
1922 platform_check_and_update_island_power_status(adev->platform,
1923 uc_info,
1924 snd_device)) {
1925 force_routing = true;
1926 ALOGD("%s:becf: force routing %d for power mode supported device",
1927 __func__, force_routing);
1928 }
1929
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001930 /*
1931 * This function is to make sure that all the active capture usecases
1932 * are always routed to the same input sound device.
1933 * For example, if audio-record and voice-call usecases are currently
1934 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1935 * is received for voice call then we have to make sure that audio-record
1936 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1937 * because of the limitation that two devices cannot be enabled
1938 * at the same time if they share the same backend.
1939 */
1940 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1941 switch_device[i] = false;
1942
1943 list_for_each(node, &adev->usecase_list) {
1944 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301945 /*
1946 * TODO: Enhance below condition to handle BT sco/USB multi recording
1947 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301948
1949 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1950 (usecase->in_snd_device != snd_device || force_routing));
1951 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1952 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1953 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001954 ((backend_check_cond &&
1955 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001956 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001957 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001958 is_single_device_type_equal(&usecase->device_list,
1959 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001960 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001961 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001962 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301963 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001964 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001965 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001966 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001967 switch_device[usecase->id] = true;
1968 num_uc_to_switch++;
1969 }
1970 }
1971
1972 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001973 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001974
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301975 /* Make sure the previous devices to be disabled first and then enable the
1976 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001977 list_for_each(node, &adev->usecase_list) {
1978 usecase = node_to_item(node, struct audio_usecase, list);
1979 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001980 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001981 }
1982 }
1983
1984 list_for_each(node, &adev->usecase_list) {
1985 usecase = node_to_item(node, struct audio_usecase, list);
1986 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001987 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001988 }
1989 }
1990
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001991 /* Re-route all the usecases on the shared backend other than the
1992 specified usecase to new snd devices */
1993 list_for_each(node, &adev->usecase_list) {
1994 usecase = node_to_item(node, struct audio_usecase, list);
1995 /* Update the in_snd_device only before enabling the audio route */
1996 if (switch_device[usecase->id] ) {
1997 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001998 if (usecase->type != VOICE_CALL) {
1999 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302000 if (usecase->type == VOIP_CALL) {
2001 snd_device_t voip_snd_device;
2002 voip_snd_device = platform_get_output_snd_device(adev->platform,
2003 uc_info->stream.out,
2004 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002005 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302006 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002007 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302008 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302009 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002010 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002011 }
2012 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002013 }
2014}
2015
Mingming Yin3a941d42016-02-17 18:08:05 -08002016static void reset_hdmi_sink_caps(struct stream_out *out) {
2017 int i = 0;
2018
2019 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2020 out->supported_channel_masks[i] = 0;
2021 }
2022 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2023 out->supported_formats[i] = 0;
2024 }
2025 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2026 out->supported_sample_rates[i] = 0;
2027 }
2028}
2029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002031static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032{
Mingming Yin3a941d42016-02-17 18:08:05 -08002033 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002034 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2035 out->extconn.cs.controller,
2036 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037
Mingming Yin3a941d42016-02-17 18:08:05 -08002038 reset_hdmi_sink_caps(out);
2039
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002040 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002041 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002042 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002043 out->extconn.cs.stream);
2044 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002045 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002046 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002047 }
2048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002051 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002052 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002053 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2054 case 6:
2055 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2056 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2057 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2058 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2059 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2060 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 break;
2062 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002063 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002064 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065 break;
2066 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002067
2068 // check channel format caps
2069 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002070 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2071 out->extconn.cs.controller,
2072 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002073 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2074 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2075 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2076 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2077 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2078 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2079 }
2080
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002081 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2082 out->extconn.cs.controller,
2083 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002084 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2085 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2086 }
2087
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002088 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2089 out->extconn.cs.controller,
2090 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002091 ALOGV(":%s HDMI supports DTS format", __func__);
2092 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2093 }
2094
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002095 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2096 out->extconn.cs.controller,
2097 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002098 ALOGV(":%s HDMI supports DTS HD format", __func__);
2099 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2100 }
2101
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002102 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2103 out->extconn.cs.controller,
2104 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002105 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2106 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2107 }
2108
Mingming Yin3a941d42016-02-17 18:08:05 -08002109
2110 // check sample rate caps
2111 i = 0;
2112 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002113 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2114 out->extconn.cs.controller,
2115 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002116 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2117 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2118 }
2119 }
2120
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002121 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122}
2123
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002124static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2125 uint32_t *supported_sample_rates __unused,
2126 uint32_t max_rates __unused)
2127{
2128 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2129 supported_sample_rates,
2130 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302131 ssize_t i = 0;
2132
2133 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002134 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2135 supported_sample_rates[i]);
2136 }
2137 return count;
2138}
2139
2140static inline int read_usb_sup_channel_masks(bool is_playback,
2141 audio_channel_mask_t *supported_channel_masks,
2142 uint32_t max_masks)
2143{
2144 int channels = audio_extn_usb_get_max_channels(is_playback);
2145 int channel_count;
2146 uint32_t num_masks = 0;
2147 if (channels > MAX_HIFI_CHANNEL_COUNT)
2148 channels = MAX_HIFI_CHANNEL_COUNT;
2149
2150 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002151 // start from 2 channels as framework currently doesn't support mono.
2152 if (channels >= FCC_2) {
2153 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2154 }
2155 for (channel_count = FCC_2;
2156 channel_count <= channels && num_masks < max_masks;
2157 ++channel_count) {
2158 supported_channel_masks[num_masks++] =
2159 audio_channel_mask_for_index_assignment_from_count(channel_count);
2160 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002161 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002162 // For capture we report all supported channel masks from 1 channel up.
2163 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002164 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2165 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002166 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2167 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2168 if (channel_count <= FCC_2) {
2169 mask = audio_channel_in_mask_from_count(channel_count);
2170 supported_channel_masks[num_masks++] = mask;
2171 }
2172 const audio_channel_mask_t index_mask =
2173 audio_channel_mask_for_index_assignment_from_count(channel_count);
2174 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2175 supported_channel_masks[num_masks++] = index_mask;
2176 }
2177 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002178 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302179
vincenttewf51c94e2019-05-07 10:28:53 +08002180 for (size_t i = 0; i < num_masks; ++i) {
2181 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2182 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302183 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002184 return num_masks;
2185}
2186
2187static inline int read_usb_sup_formats(bool is_playback __unused,
2188 audio_format_t *supported_formats,
2189 uint32_t max_formats __unused)
2190{
2191 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2192 switch (bitwidth) {
2193 case 24:
2194 // XXX : usb.c returns 24 for s24 and s24_le?
2195 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2196 break;
2197 case 32:
2198 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2199 break;
2200 case 16:
2201 default :
2202 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2203 break;
2204 }
2205 ALOGV("%s: %s supported format %d", __func__,
2206 is_playback ? "P" : "C", bitwidth);
2207 return 1;
2208}
2209
2210static inline int read_usb_sup_params_and_compare(bool is_playback,
2211 audio_format_t *format,
2212 audio_format_t *supported_formats,
2213 uint32_t max_formats,
2214 audio_channel_mask_t *mask,
2215 audio_channel_mask_t *supported_channel_masks,
2216 uint32_t max_masks,
2217 uint32_t *rate,
2218 uint32_t *supported_sample_rates,
2219 uint32_t max_rates) {
2220 int ret = 0;
2221 int num_formats;
2222 int num_masks;
2223 int num_rates;
2224 int i;
2225
2226 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2227 max_formats);
2228 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2229 max_masks);
2230
2231 num_rates = read_usb_sup_sample_rates(is_playback,
2232 supported_sample_rates, max_rates);
2233
2234#define LUT(table, len, what, dflt) \
2235 for (i=0; i<len && (table[i] != what); i++); \
2236 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2237
2238 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2239 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2240 LUT(supported_sample_rates, num_rates, *rate, 0);
2241
2242#undef LUT
2243 return ret < 0 ? -EINVAL : 0; // HACK TBD
2244}
2245
Alexy Josephb1379942016-01-29 15:49:38 -08002246audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002247 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002248{
2249 struct audio_usecase *usecase;
2250 struct listnode *node;
2251
2252 list_for_each(node, &adev->usecase_list) {
2253 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002254 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002255 ALOGV("%s: usecase id %d", __func__, usecase->id);
2256 return usecase->id;
2257 }
2258 }
2259 return USECASE_INVALID;
2260}
2261
Alexy Josephb1379942016-01-29 15:49:38 -08002262struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002263 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002264{
2265 struct audio_usecase *usecase;
2266 struct listnode *node;
2267
2268 list_for_each(node, &adev->usecase_list) {
2269 usecase = node_to_item(node, struct audio_usecase, list);
2270 if (usecase->id == uc_id)
2271 return usecase;
2272 }
2273 return NULL;
2274}
2275
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302276/*
2277 * is a true native playback active
2278 */
2279bool audio_is_true_native_stream_active(struct audio_device *adev)
2280{
2281 bool active = false;
2282 int i = 0;
2283 struct listnode *node;
2284
2285 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2286 ALOGV("%s:napb: not in true mode or non hdphones device",
2287 __func__);
2288 active = false;
2289 goto exit;
2290 }
2291
2292 list_for_each(node, &adev->usecase_list) {
2293 struct audio_usecase *uc;
2294 uc = node_to_item(node, struct audio_usecase, list);
2295 struct stream_out *curr_out =
2296 (struct stream_out*) uc->stream.out;
2297
2298 if (curr_out && PCM_PLAYBACK == uc->type) {
2299 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2300 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2301 uc->id, curr_out->sample_rate,
2302 curr_out->bit_width,
2303 platform_get_snd_device_name(uc->out_snd_device));
2304
2305 if (is_offload_usecase(uc->id) &&
2306 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2307 active = true;
2308 ALOGD("%s:napb:native stream detected", __func__);
2309 }
2310 }
2311 }
2312exit:
2313 return active;
2314}
2315
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002316uint32_t adev_get_dsp_bit_width_enforce_mode()
2317{
2318 if (adev == NULL) {
2319 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2320 return 0;
2321 }
2322 return adev->dsp_bit_width_enforce_mode;
2323}
2324
2325static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2326{
2327 char value[PROPERTY_VALUE_MAX];
2328 int trial;
2329 uint32_t dsp_bit_width_enforce_mode = 0;
2330
2331 if (!mixer) {
2332 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2333 __func__);
2334 return 0;
2335 }
2336
2337 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2338 value, NULL) > 0) {
2339 trial = atoi(value);
2340 switch (trial) {
2341 case 16:
2342 dsp_bit_width_enforce_mode = 16;
2343 break;
2344 case 24:
2345 dsp_bit_width_enforce_mode = 24;
2346 break;
2347 case 32:
2348 dsp_bit_width_enforce_mode = 32;
2349 break;
2350 default:
2351 dsp_bit_width_enforce_mode = 0;
2352 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2353 break;
2354 }
2355 }
2356
2357 return dsp_bit_width_enforce_mode;
2358}
2359
2360static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2361 uint32_t enforce_mode,
2362 bool enable)
2363{
2364 struct mixer_ctl *ctl = NULL;
2365 const char *mixer_ctl_name = "ASM Bit Width";
2366 uint32_t asm_bit_width_mode = 0;
2367
2368 if (enforce_mode == 0) {
2369 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2370 return;
2371 }
2372
2373 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2374 if (!ctl) {
2375 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2376 __func__, mixer_ctl_name);
2377 return;
2378 }
2379
2380 if (enable)
2381 asm_bit_width_mode = enforce_mode;
2382 else
2383 asm_bit_width_mode = 0;
2384
2385 ALOGV("%s DSP bit width feature status is %d width=%d",
2386 __func__, enable, asm_bit_width_mode);
2387 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2388 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2389 asm_bit_width_mode);
2390
2391 return;
2392}
2393
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302394/*
2395 * if native DSD playback active
2396 */
2397bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2398{
2399 bool active = false;
2400 struct listnode *node = NULL;
2401 struct audio_usecase *uc = NULL;
2402 struct stream_out *curr_out = NULL;
2403
2404 list_for_each(node, &adev->usecase_list) {
2405 uc = node_to_item(node, struct audio_usecase, list);
2406 curr_out = (struct stream_out*) uc->stream.out;
2407
2408 if (curr_out && PCM_PLAYBACK == uc->type &&
2409 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2410 active = true;
2411 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302412 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302413 }
2414 }
2415 return active;
2416}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302417
2418static bool force_device_switch(struct audio_usecase *usecase)
2419{
2420 bool ret = false;
2421 bool is_it_true_mode = false;
2422
Zhou Song30f2c3e2018-02-08 14:02:15 +08002423 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302424 usecase->type == TRANSCODE_LOOPBACK_RX ||
2425 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002426 return false;
2427 }
2428
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002429 if(usecase->stream.out == NULL) {
2430 ALOGE("%s: stream.out is NULL", __func__);
2431 return false;
2432 }
2433
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302434 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002435 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002436 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2437 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302438 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2439 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2440 (!is_it_true_mode && adev->native_playback_enabled)){
2441 ret = true;
2442 ALOGD("napb: time to toggle native mode");
2443 }
2444 }
2445
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302446 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302447 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2448 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002449 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302450 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302451 ALOGD("Force a2dp device switch to update new encoder config");
2452 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002453 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302454
Florian Pfister1a84f312018-07-19 14:38:18 +02002455 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302456 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2457 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002458 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302459 return ret;
2460}
2461
Aalique Grahame22e49102018-12-18 14:23:57 -08002462static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2463{
2464 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2465}
2466
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302467bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2468{
2469 bool ret=false;
2470 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002471 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2472 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302473 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2474 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002475 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302476 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002477 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2478 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302479 ret = true;
2480
2481 return ret;
2482}
2483
2484bool is_a2dp_device(snd_device_t out_snd_device)
2485{
2486 bool ret=false;
2487 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2488 ret = true;
2489
2490 return ret;
2491}
2492
2493bool is_bt_soc_on(struct audio_device *adev)
2494{
2495 struct mixer_ctl *ctl;
2496 char *mixer_ctl_name = "BT SOC status";
2497 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2498 bool bt_soc_status = true;
2499 if (!ctl) {
2500 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2501 __func__, mixer_ctl_name);
2502 /*This is to ensure we dont break targets which dont have the kernel change*/
2503 return true;
2504 }
2505 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2506 ALOGD("BT SOC status: %d",bt_soc_status);
2507 return bt_soc_status;
2508}
2509
Zhou Song331c8e52019-08-26 14:16:12 +08002510static int configure_btsco_sample_rate(snd_device_t snd_device)
2511{
2512 struct mixer_ctl *ctl = NULL;
2513 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2514 char *rate_str = NULL;
2515 bool is_rx_dev = true;
2516
2517 if (is_btsco_device(snd_device, snd_device)) {
2518 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2519 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2520 if (!ctl_sr_tx || !ctl_sr_rx) {
2521 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2522 if (!ctl_sr)
2523 return -ENOSYS;
2524 }
2525
2526 switch (snd_device) {
2527 case SND_DEVICE_OUT_BT_SCO:
2528 rate_str = "KHZ_8";
2529 break;
2530 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2531 case SND_DEVICE_IN_BT_SCO_MIC:
2532 rate_str = "KHZ_8";
2533 is_rx_dev = false;
2534 break;
2535 case SND_DEVICE_OUT_BT_SCO_WB:
2536 rate_str = "KHZ_16";
2537 break;
2538 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2539 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2540 rate_str = "KHZ_16";
2541 is_rx_dev = false;
2542 break;
2543 default:
2544 return 0;
2545 }
2546
2547 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2548 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2549 return -ENOSYS;
2550 }
2551 return 0;
2552}
2553
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302554int out_standby_l(struct audio_stream *stream);
2555
Eric Laurent637e2d42018-11-15 12:24:31 -08002556struct stream_in *adev_get_active_input(const struct audio_device *adev)
2557{
2558 struct listnode *node;
2559 struct stream_in *last_active_in = NULL;
2560
2561 /* Get last added active input.
2562 * TODO: We may use a priority mechanism to pick highest priority active source */
2563 list_for_each(node, &adev->usecase_list)
2564 {
2565 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2566 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2567 last_active_in = usecase->stream.in;
2568 }
2569
2570 return last_active_in;
2571}
2572
2573struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2574{
2575 struct listnode *node;
2576
2577 /* First check active inputs with voice communication source and then
2578 * any input if audio mode is in communication */
2579 list_for_each(node, &adev->usecase_list)
2580 {
2581 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2582 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2583 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2584 return usecase->stream.in;
2585 }
2586 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2587 return adev_get_active_input(adev);
2588
2589 return NULL;
2590}
2591
Carter Hsu2e429db2019-05-14 18:50:52 +08002592/*
2593 * Aligned with policy.h
2594 */
2595static inline int source_priority(int inputSource)
2596{
2597 switch (inputSource) {
2598 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2599 return 9;
2600 case AUDIO_SOURCE_CAMCORDER:
2601 return 8;
2602 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2603 return 7;
2604 case AUDIO_SOURCE_UNPROCESSED:
2605 return 6;
2606 case AUDIO_SOURCE_MIC:
2607 return 5;
2608 case AUDIO_SOURCE_ECHO_REFERENCE:
2609 return 4;
2610 case AUDIO_SOURCE_FM_TUNER:
2611 return 3;
2612 case AUDIO_SOURCE_VOICE_RECOGNITION:
2613 return 2;
2614 case AUDIO_SOURCE_HOTWORD:
2615 return 1;
2616 default:
2617 break;
2618 }
2619 return 0;
2620}
2621
2622static struct stream_in *get_priority_input(struct audio_device *adev)
2623{
2624 struct listnode *node;
2625 struct audio_usecase *usecase;
2626 int last_priority = 0, priority;
2627 struct stream_in *priority_in = NULL;
2628 struct stream_in *in;
2629
2630 list_for_each(node, &adev->usecase_list) {
2631 usecase = node_to_item(node, struct audio_usecase, list);
2632 if (usecase->type == PCM_CAPTURE) {
2633 in = usecase->stream.in;
2634 if (!in)
2635 continue;
2636 priority = source_priority(in->source);
2637
2638 if (priority > last_priority) {
2639 last_priority = priority;
2640 priority_in = in;
2641 }
2642 }
2643 }
2644 return priority_in;
2645}
2646
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002647int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002649 snd_device_t out_snd_device = SND_DEVICE_NONE;
2650 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002651 struct audio_usecase *usecase = NULL;
2652 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002653 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002654 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302655 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002656 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002657 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302659 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2660
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002661 usecase = get_usecase_from_list(adev, uc_id);
2662 if (usecase == NULL) {
2663 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2664 return -EINVAL;
2665 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002667 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002668 (usecase->type == VOIP_CALL) ||
2669 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302670 if(usecase->stream.out == NULL) {
2671 ALOGE("%s: stream.out is NULL", __func__);
2672 return -EINVAL;
2673 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002674 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002675 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2676 uc_id);
2677 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2678 uc_id);
2679 } else {
2680 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302681 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002682 in_snd_device = platform_get_input_snd_device(adev->platform,
2683 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302684 &usecase->stream.out->device_list,
2685 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002686 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002687 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302688 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302689 if (usecase->stream.inout == NULL) {
2690 ALOGE("%s: stream.inout is NULL", __func__);
2691 return -EINVAL;
2692 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002693 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302694 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2695 stream_out.format = usecase->stream.inout->out_config.format;
2696 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302697 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002698 assign_devices(&usecase->device_list,
2699 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302700 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2701 if (usecase->stream.inout == NULL) {
2702 ALOGE("%s: stream.inout is NULL", __func__);
2703 return -EINVAL;
2704 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302705 struct listnode out_devices;
2706 list_init(&out_devices);
2707 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2708 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002709 assign_devices(&usecase->device_list,
2710 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002711 } else {
2712 /*
2713 * If the voice call is active, use the sound devices of voice call usecase
2714 * so that it would not result any device switch. All the usecases will
2715 * be switched to new device when select_devices() is called for voice call
2716 * usecase. This is to avoid switching devices for voice call when
2717 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002718 * choose voice call device only if the use case device is
2719 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002720 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002721 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002722 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002723 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002724 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2725 is_codec_backend_out_device_type(&usecase->device_list)) ||
2726 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2727 is_codec_backend_in_device_type(&usecase->device_list)) ||
2728 is_single_device_type_equal(&vc_usecase->device_list,
2729 AUDIO_DEVICE_OUT_HEARING_AID) ||
2730 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002731 AUDIO_DEVICE_IN_VOICE_CALL) ||
2732 (is_single_device_type_equal(&usecase->device_list,
2733 AUDIO_DEVICE_IN_USB_HEADSET) &&
2734 is_single_device_type_equal(&vc_usecase->device_list,
2735 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002736 in_snd_device = vc_usecase->in_snd_device;
2737 out_snd_device = vc_usecase->out_snd_device;
2738 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002739 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002740 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002741 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002742 if ((voip_usecase != NULL) &&
2743 (usecase->type == PCM_PLAYBACK) &&
2744 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002745 out_snd_device_backend_match = platform_check_backends_match(
2746 voip_usecase->out_snd_device,
2747 platform_get_output_snd_device(
2748 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302749 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002750 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002751 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2752 (is_codec_backend_out_device_type(&usecase->device_list) ||
2753 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002754 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002755 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002756 in_snd_device = voip_usecase->in_snd_device;
2757 out_snd_device = voip_usecase->out_snd_device;
2758 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002759 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002760 hfp_ucid = audio_extn_hfp_get_usecase();
2761 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002762 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002763 in_snd_device = hfp_usecase->in_snd_device;
2764 out_snd_device = hfp_usecase->out_snd_device;
2765 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002766 }
2767 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302768 if (usecase->stream.out == NULL) {
2769 ALOGE("%s: stream.out is NULL", __func__);
2770 return -EINVAL;
2771 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002772 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002773 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002774 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002775 struct stream_out *voip_out = adev->primary_output;
2776 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002777 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002778 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2779 else
2780 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302781 usecase->stream.out,
2782 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002783 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002784
Eric Laurent637e2d42018-11-15 12:24:31 -08002785 if (voip_usecase)
2786 voip_out = voip_usecase->stream.out;
2787
2788 if (usecase->stream.out == voip_out && voip_in != NULL)
2789 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002790 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002791 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302792 if (usecase->stream.in == NULL) {
2793 ALOGE("%s: stream.in is NULL", __func__);
2794 return -EINVAL;
2795 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002796 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002797 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002798 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002799 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002800 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002801 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002802
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002803 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002804 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002805 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2806 USECASE_AUDIO_PLAYBACK_VOIP);
2807
Carter Hsu2e429db2019-05-14 18:50:52 +08002808 usecase->stream.in->enable_ec_port = false;
2809
Zhou Song62ea0282020-03-22 19:53:01 +08002810 bool is_ha_usecase = adev->ha_proxy_enable ?
2811 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2812 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2813 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002814 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002815 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002816 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002817 } else if (adev->primary_output &&
2818 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002819 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002820 } else {
2821 /* forcing speaker o/p device to get matching i/p pair
2822 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002823 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002824 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002825 priority_in = voip_in;
2826 } else {
2827 /* get the input with the highest priority source*/
2828 priority_in = get_priority_input(adev);
2829
2830 if (!priority_in)
2831 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002832 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002833
Eric Laurent637e2d42018-11-15 12:24:31 -08002834 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002835 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302836 &out_devices,
2837 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002838 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002839 }
2840 }
2841
2842 if (out_snd_device == usecase->out_snd_device &&
2843 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302844
2845 if (!force_device_switch(usecase))
2846 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847 }
2848
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002849 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002850 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002851 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002852 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2853 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302854 }
2855
Aalique Grahame22e49102018-12-18 14:23:57 -08002856 if (out_snd_device != SND_DEVICE_NONE &&
2857 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2858 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2859 __func__,
2860 use_case_table[uc_id],
2861 adev->last_logged_snd_device[uc_id][0],
2862 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2863 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2864 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2865 -1,
2866 out_snd_device,
2867 platform_get_snd_device_name(out_snd_device),
2868 platform_get_snd_device_acdb_id(out_snd_device));
2869 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2870 }
2871 if (in_snd_device != SND_DEVICE_NONE &&
2872 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2873 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2874 __func__,
2875 use_case_table[uc_id],
2876 adev->last_logged_snd_device[uc_id][1],
2877 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2878 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2879 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2880 -1,
2881 in_snd_device,
2882 platform_get_snd_device_name(in_snd_device),
2883 platform_get_snd_device_acdb_id(in_snd_device));
2884 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2885 }
2886
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888 /*
2889 * Limitation: While in call, to do a device switch we need to disable
2890 * and enable both RX and TX devices though one of them is same as current
2891 * device.
2892 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002893 if ((usecase->type == VOICE_CALL) &&
2894 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2895 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002896 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002897 }
2898
2899 if (((usecase->type == VOICE_CALL) ||
2900 (usecase->type == VOIP_CALL)) &&
2901 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2902 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302903 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002904 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002905 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002906
2907 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302908 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002909 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002910 }
2911
Aalique Grahame22e49102018-12-18 14:23:57 -08002912 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2913 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002914 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302915 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002916 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2917 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2918 else
2919 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302920 }
2921
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002922 /* Disable current sound devices */
2923 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002924 disable_audio_route(adev, usecase);
2925 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002926 }
2927
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002928 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002929 disable_audio_route(adev, usecase);
2930 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931 }
2932
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002933 /* Applicable only on the targets that has external modem.
2934 * New device information should be sent to modem before enabling
2935 * the devices to reduce in-call device switch time.
2936 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002937 if ((usecase->type == VOICE_CALL) &&
2938 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2939 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002940 status = platform_switch_voice_call_enable_device_config(adev->platform,
2941 out_snd_device,
2942 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002943 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002944
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002945 /* Enable new sound devices */
2946 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002947 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302948 if (platform_check_codec_asrc_support(adev->platform))
2949 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002950 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951 }
2952
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002953 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302954 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002955 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002956 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002957
Avinash Vaish71a8b972014-07-24 15:36:33 +05302958 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002959 status = platform_switch_voice_call_device_post(adev->platform,
2960 out_snd_device,
2961 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302962 enable_audio_route_for_voice_usecases(adev, usecase);
2963 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002964
sangwoo170731f2013-06-08 15:36:36 +09002965 usecase->in_snd_device = in_snd_device;
2966 usecase->out_snd_device = out_snd_device;
2967
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302968 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2969 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302970 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002971 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002972 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002973 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2974 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2975 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2976 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2977 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2978 /*
2979 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2980 * configured device sample rate, if not update the COPP rate to be equal to the
2981 * device sample rate, else open COPP at stream sample rate
2982 */
2983 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2984 usecase->stream.out->sample_rate,
2985 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302986 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302987 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2988 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302989 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002990 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2991 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2992 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2993 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002994 }
2995 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002996
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002997 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002998
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002999 /* If input stream is already running then effect needs to be
3000 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003001 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003002 check_and_enable_effect(adev);
3003
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003004 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003005 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303006 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003007 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3008
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003009 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303010 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003011 voice_extn_compress_voip_is_started(adev))
3012 voice_set_sidetone(adev, out_snd_device, true);
3013 }
3014
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003015 /* Applicable only on the targets that has external modem.
3016 * Enable device command should be sent to modem only after
3017 * enabling voice call mixer controls
3018 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003019 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003020 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3021 out_snd_device,
3022 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303023
3024 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003025 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303026 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003027 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303028 if (is_bt_soc_on(adev) == false){
3029 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003030 if (in->pcm != NULL)
3031 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303032 }
3033 }
3034 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3035 && usecase->stream.out->started) {
3036 if (is_bt_soc_on(adev) == false) {
3037 ALOGD("BT SCO/A2DP disconnected while in connection");
3038 out_standby_l(&usecase->stream.out->stream.common);
3039 }
3040 }
3041 } else if ((usecase->stream.out != NULL) &&
3042 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303043 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3044 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003045 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303046 usecase->stream.out->started) {
3047 if (is_bt_soc_on(adev) == false) {
3048 ALOGD("BT SCO/A2dp disconnected while in connection");
3049 out_standby_l(&usecase->stream.out->stream.common);
3050 }
3051 }
3052 }
3053
Yung Ti Su70cb8242018-06-22 17:38:47 +08003054 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003055 struct stream_out *voip_out = voip_usecase->stream.out;
3056 audio_extn_utils_send_app_type_gain(adev,
3057 voip_out->app_type_cfg.app_type,
3058 &voip_out->app_type_cfg.gain[0]);
3059 }
3060
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303061 ALOGD("%s: done",__func__);
3062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063 return status;
3064}
3065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066static int stop_input_stream(struct stream_in *in)
3067{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303068 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303070
3071 if (in == NULL) {
3072 ALOGE("%s: stream_in ptr is NULL", __func__);
3073 return -EINVAL;
3074 }
3075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003077 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078
Eric Laurent994a6932013-07-17 11:51:42 -07003079 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003080 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081 uc_info = get_usecase_from_list(adev, in->usecase);
3082 if (uc_info == NULL) {
3083 ALOGE("%s: Could not find the usecase (%d) in the list",
3084 __func__, in->usecase);
3085 return -EINVAL;
3086 }
3087
Carter Hsu2e429db2019-05-14 18:50:52 +08003088 priority_in = get_priority_input(adev);
3089
Derek Chenea197282019-01-07 17:35:01 -08003090 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3091 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003092
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003093 /* Close in-call recording streams */
3094 voice_check_and_stop_incall_rec_usecase(adev, in);
3095
Eric Laurent150dbfe2013-02-27 14:31:02 -08003096 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003097 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003098
3099 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003100 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003102 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303103 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3104
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003105 list_remove(&uc_info->list);
3106 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107
Carter Hsu2e429db2019-05-14 18:50:52 +08003108 if (priority_in == in) {
3109 priority_in = get_priority_input(adev);
3110 if (priority_in)
3111 select_devices(adev, priority_in->usecase);
3112 }
3113
Vatsal Buchac09ae062018-11-14 13:25:08 +05303114 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003115 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 return ret;
3117}
3118
3119int start_input_stream(struct stream_in *in)
3120{
3121 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003122 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303124
3125 if (in == NULL) {
3126 ALOGE("%s: stream_in ptr is NULL", __func__);
3127 return -EINVAL;
3128 }
3129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003131 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003132 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133
Mingming Yin2664a5b2015-09-03 10:53:11 -07003134 if (get_usecase_from_list(adev, usecase) == NULL)
3135 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303136 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3137 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003138
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303139 if (CARD_STATUS_OFFLINE == in->card_status||
3140 CARD_STATUS_OFFLINE == adev->card_status) {
3141 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303142 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303143 goto error_config;
3144 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303145
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003146 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303147 if (!adev->bt_sco_on) {
3148 ALOGE("%s: SCO profile is not ready, return error", __func__);
3149 ret = -EIO;
3150 goto error_config;
3151 }
3152 }
3153
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003154 /* Check if source matches incall recording usecase criteria */
3155 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3156 if (ret)
3157 goto error_config;
3158 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003159 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3160
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303161 if (audio_extn_cin_attached_usecase(in))
3162 audio_extn_cin_acquire_usecase(in);
3163
Mingming Yin2664a5b2015-09-03 10:53:11 -07003164 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3165 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3166 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003167 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003168 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003169
Eric Laurentb23d5282013-05-14 15:27:20 -07003170 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 if (in->pcm_device_id < 0) {
3172 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3173 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003174 ret = -EINVAL;
3175 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003179
3180 if (!uc_info) {
3181 ret = -ENOMEM;
3182 goto error_config;
3183 }
3184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 uc_info->id = in->usecase;
3186 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003187 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003188 list_init(&uc_info->device_list);
3189 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003190 uc_info->in_snd_device = SND_DEVICE_NONE;
3191 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003193 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003194 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303195 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3196 adev->perf_lock_opts,
3197 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003198 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199
Derek Chenea197282019-01-07 17:35:01 -08003200 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3201 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003202
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303203 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3204
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303205 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303206 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303207 if (ret)
3208 goto error_open;
3209 else
3210 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003211 }
3212
Haynes Mathew George16081042017-05-31 17:16:49 -07003213 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003214 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003215 ALOGE("%s: pcm stream not ready", __func__);
3216 goto error_open;
3217 }
3218 ret = pcm_start(in->pcm);
3219 if (ret < 0) {
3220 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3221 goto error_open;
3222 }
3223 } else {
3224 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3225 unsigned int pcm_open_retry_count = 0;
3226
Zhou Song62ea0282020-03-22 19:53:01 +08003227 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3228 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003229 flags |= PCM_MMAP | PCM_NOIRQ;
3230 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3231 } else if (in->realtime) {
3232 flags |= PCM_MMAP | PCM_NOIRQ;
3233 }
3234
Garmond Leunge2433c32017-09-28 21:51:22 -07003235 if (audio_extn_ffv_get_stream() == in) {
3236 ALOGD("%s: ffv stream, update pcm config", __func__);
3237 audio_extn_ffv_update_pcm_config(&config);
3238 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003239 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3240 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3241
3242 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003243 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003244 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003245 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003246 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303247 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303248 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3249 adev->card_status = CARD_STATUS_OFFLINE;
3250 in->card_status = CARD_STATUS_OFFLINE;
3251 ret = -EIO;
3252 goto error_open;
3253 }
3254
Haynes Mathew George16081042017-05-31 17:16:49 -07003255 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3256 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3257 if (in->pcm != NULL) {
3258 pcm_close(in->pcm);
3259 in->pcm = NULL;
3260 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003261 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003262 ret = -EIO;
3263 goto error_open;
3264 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003265 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003266 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3267 continue;
3268 }
3269 break;
3270 }
3271
3272 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003273 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003274 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003275 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003276 if (ret < 0) {
3277 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3278 pcm_close(in->pcm);
3279 in->pcm = NULL;
3280 goto error_open;
3281 }
3282 register_in_stream(in);
3283 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003284 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003285 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003286 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003287 if (ret < 0) {
3288 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003289 pcm_close(in->pcm);
3290 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003291 goto error_open;
3292 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003293 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003294 }
3295
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003296 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003297 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3298 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003299
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003300 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303301 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3302
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303303done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003304 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303305 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003306 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303307 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003308 return ret;
3309
3310error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003311 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303312 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003314
Eric Laurentc8400632013-02-14 19:04:54 -08003315error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303316 /*
3317 * sleep 50ms to allow sufficient time for kernel
3318 * drivers to recover incases like SSR.
3319 */
3320 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003321 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303322 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003323 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324}
3325
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003326void lock_input_stream(struct stream_in *in)
3327{
3328 pthread_mutex_lock(&in->pre_lock);
3329 pthread_mutex_lock(&in->lock);
3330 pthread_mutex_unlock(&in->pre_lock);
3331}
3332
3333void lock_output_stream(struct stream_out *out)
3334{
3335 pthread_mutex_lock(&out->pre_lock);
3336 pthread_mutex_lock(&out->lock);
3337 pthread_mutex_unlock(&out->pre_lock);
3338}
3339
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003340/* must be called with out->lock locked */
3341static int send_offload_cmd_l(struct stream_out* out, int command)
3342{
3343 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3344
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003345 if (!cmd) {
3346 ALOGE("failed to allocate mem for command 0x%x", command);
3347 return -ENOMEM;
3348 }
3349
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003350 ALOGVV("%s %d", __func__, command);
3351
3352 cmd->cmd = command;
3353 list_add_tail(&out->offload_cmd_list, &cmd->node);
3354 pthread_cond_signal(&out->offload_cond);
3355 return 0;
3356}
3357
3358/* must be called iwth out->lock locked */
3359static void stop_compressed_output_l(struct stream_out *out)
3360{
3361 out->offload_state = OFFLOAD_STATE_IDLE;
3362 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003363 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003364 if (out->compr != NULL) {
3365 compress_stop(out->compr);
3366 while (out->offload_thread_blocked) {
3367 pthread_cond_wait(&out->cond, &out->lock);
3368 }
3369 }
3370}
3371
Varun Balaraje49253e2017-07-06 19:48:56 +05303372bool is_interactive_usecase(audio_usecase_t uc_id)
3373{
3374 unsigned int i;
3375 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3376 if (uc_id == interactive_usecases[i])
3377 return true;
3378 }
3379 return false;
3380}
3381
3382static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3383{
3384 audio_usecase_t ret_uc = USECASE_INVALID;
3385 unsigned int intract_uc_index;
3386 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3387
3388 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3389 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3390 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3391 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3392 ret_uc = interactive_usecases[intract_uc_index];
3393 break;
3394 }
3395 }
3396
3397 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3398 return ret_uc;
3399}
3400
3401static void free_interactive_usecase(struct audio_device *adev,
3402 audio_usecase_t uc_id)
3403{
3404 unsigned int interact_uc_index;
3405 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3406
3407 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3408 if (interactive_usecases[interact_uc_index] == uc_id) {
3409 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3410 break;
3411 }
3412 }
3413 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3414}
3415
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003416bool is_offload_usecase(audio_usecase_t uc_id)
3417{
3418 unsigned int i;
3419 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3420 if (uc_id == offload_usecases[i])
3421 return true;
3422 }
3423 return false;
3424}
3425
Dhananjay Kumarac341582017-02-23 23:42:25 +05303426static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003427{
vivek mehta446c3962015-09-14 10:57:35 -07003428 audio_usecase_t ret_uc = USECASE_INVALID;
3429 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003430 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003431 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303432 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003433 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3434 else
3435 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003436
vivek mehta446c3962015-09-14 10:57:35 -07003437 pthread_mutex_lock(&adev->lock);
3438 if (get_usecase_from_list(adev, ret_uc) != NULL)
3439 ret_uc = USECASE_INVALID;
3440 pthread_mutex_unlock(&adev->lock);
3441
3442 return ret_uc;
3443 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003444
3445 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003446 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3447 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3448 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3449 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003450 break;
3451 }
3452 }
vivek mehta446c3962015-09-14 10:57:35 -07003453
3454 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3455 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003456}
3457
3458static void free_offload_usecase(struct audio_device *adev,
3459 audio_usecase_t uc_id)
3460{
vivek mehta446c3962015-09-14 10:57:35 -07003461 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003462 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003463
3464 if (!adev->multi_offload_enable)
3465 return;
3466
3467 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3468 if (offload_usecases[offload_uc_index] == uc_id) {
3469 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003470 break;
3471 }
3472 }
3473 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3474}
3475
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003476static void *offload_thread_loop(void *context)
3477{
3478 struct stream_out *out = (struct stream_out *) context;
3479 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003480 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003481
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003482 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003483 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003484 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3485
3486 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003487 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003488 out->offload_state = OFFLOAD_STATE_IDLE;
3489 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490 for (;;) {
3491 struct offload_cmd *cmd = NULL;
3492 stream_callback_event_t event;
3493 bool send_callback = false;
3494
3495 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3496 __func__, list_empty(&out->offload_cmd_list),
3497 out->offload_state);
3498 if (list_empty(&out->offload_cmd_list)) {
3499 ALOGV("%s SLEEPING", __func__);
3500 pthread_cond_wait(&out->offload_cond, &out->lock);
3501 ALOGV("%s RUNNING", __func__);
3502 continue;
3503 }
3504
3505 item = list_head(&out->offload_cmd_list);
3506 cmd = node_to_item(item, struct offload_cmd, node);
3507 list_remove(item);
3508
3509 ALOGVV("%s STATE %d CMD %d out->compr %p",
3510 __func__, out->offload_state, cmd->cmd, out->compr);
3511
3512 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3513 free(cmd);
3514 break;
3515 }
3516
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003517 // allow OFFLOAD_CMD_ERROR reporting during standby
3518 // this is needed to handle failures during compress_open
3519 // Note however that on a pause timeout, the stream is closed
3520 // and no offload usecase will be active. Therefore this
3521 // special case is needed for compress_open failures alone
3522 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3523 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003524 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003525 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003526 pthread_cond_signal(&out->cond);
3527 continue;
3528 }
3529 out->offload_thread_blocked = true;
3530 pthread_mutex_unlock(&out->lock);
3531 send_callback = false;
3532 switch(cmd->cmd) {
3533 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003534 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003535 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003536 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003537 send_callback = true;
3538 event = STREAM_CBK_EVENT_WRITE_READY;
3539 break;
3540 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003541 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303542 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003543 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303544 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003545 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303546 if (ret < 0)
3547 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303548 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303549 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003550 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003551 else
3552 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003553 if (-ENETRESET != ret && !(-EINTR == ret &&
3554 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303555 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303556 pthread_mutex_lock(&out->lock);
3557 out->send_new_metadata = 1;
3558 out->send_next_track_params = true;
3559 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303560 event = STREAM_CBK_EVENT_DRAIN_READY;
3561 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3562 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303563 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003564 break;
3565 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003566 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003567 ret = compress_drain(out->compr);
3568 ALOGD("copl(%p):out of compress_drain", out);
3569 // EINTR check avoids drain interruption due to SSR
3570 if (-ENETRESET != ret && !(-EINTR == ret &&
3571 CARD_STATUS_OFFLINE == out->card_status)) {
3572 send_callback = true;
3573 event = STREAM_CBK_EVENT_DRAIN_READY;
3574 } else
3575 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003576 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303577 case OFFLOAD_CMD_ERROR:
3578 ALOGD("copl(%p): sending error callback to AF", out);
3579 send_callback = true;
3580 event = STREAM_CBK_EVENT_ERROR;
3581 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003582 default:
3583 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3584 break;
3585 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003586 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003587 out->offload_thread_blocked = false;
3588 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003589 if (send_callback && out->client_callback) {
3590 ALOGVV("%s: sending client_callback event %d", __func__, event);
3591 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003592 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003593 free(cmd);
3594 }
3595
3596 pthread_cond_signal(&out->cond);
3597 while (!list_empty(&out->offload_cmd_list)) {
3598 item = list_head(&out->offload_cmd_list);
3599 list_remove(item);
3600 free(node_to_item(item, struct offload_cmd, node));
3601 }
3602 pthread_mutex_unlock(&out->lock);
3603
3604 return NULL;
3605}
3606
3607static int create_offload_callback_thread(struct stream_out *out)
3608{
3609 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3610 list_init(&out->offload_cmd_list);
3611 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3612 offload_thread_loop, out);
3613 return 0;
3614}
3615
3616static int destroy_offload_callback_thread(struct stream_out *out)
3617{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003618 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003619 stop_compressed_output_l(out);
3620 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3621
3622 pthread_mutex_unlock(&out->lock);
3623 pthread_join(out->offload_thread, (void **) NULL);
3624 pthread_cond_destroy(&out->offload_cond);
3625
3626 return 0;
3627}
3628
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629static int stop_output_stream(struct stream_out *out)
3630{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303631 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 struct audio_usecase *uc_info;
3633 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003634 bool has_voip_usecase =
3635 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636
Eric Laurent994a6932013-07-17 11:51:42 -07003637 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003638 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639 uc_info = get_usecase_from_list(adev, out->usecase);
3640 if (uc_info == NULL) {
3641 ALOGE("%s: Could not find the usecase (%d) in the list",
3642 __func__, out->usecase);
3643 return -EINVAL;
3644 }
3645
Derek Chenea197282019-01-07 17:35:01 -08003646 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3647 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003648
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003649 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303650 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003651 if (adev->visualizer_stop_output != NULL)
3652 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003653
3654 audio_extn_dts_remove_state_notifier_node(out->usecase);
3655
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003656 if (adev->offload_effects_stop_output != NULL)
3657 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003658 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3659 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3660 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003661 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003662
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003663 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3664 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003665 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003666 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003667
Eric Laurent150dbfe2013-02-27 14:31:02 -08003668 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003669 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003670
3671 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003672 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673
Aalique Grahame22e49102018-12-18 14:23:57 -08003674 audio_extn_extspk_update(adev->extspk);
3675
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003676 if (is_offload_usecase(out->usecase)) {
3677 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3678 adev->dsp_bit_width_enforce_mode,
3679 false);
3680 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003681 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003682 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3683 false);
3684
3685 if (ret != 0)
3686 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3687 /* default service interval was successfully updated,
3688 reopen USB backend with new service interval */
3689 ret = 0;
3690 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003691
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003692 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303693 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003694 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303695 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003696 ALOGV("Disable passthrough , reset mixer to pcm");
3697 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003698#ifdef AUDIO_GKI_ENABLED
3699 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3700 out->compr_config.codec->reserved[0] = 0;
3701#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003702 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003703#endif
Mingming Yin21854652016-04-13 11:54:02 -07003704 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003705 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3706 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003707
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303708 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003709 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303710 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303711
Manish Dewangan21a850a2017-08-14 12:03:55 +05303712 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003713 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3714 if (ret < 0)
3715 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3716 }
3717
juyuchen2d415992018-11-16 14:15:16 +08003718 /* 1) media + voip output routing to handset must route media back to
3719 speaker when voip stops.
3720 2) trigger voip input to reroute when voip output changes to
3721 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003722 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003723 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003724 struct listnode *node;
3725 struct audio_usecase *usecase;
3726 list_for_each(node, &adev->usecase_list) {
3727 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003728 if ((usecase->type == PCM_CAPTURE &&
3729 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3730 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003731 continue;
3732
3733 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3734 __func__, usecase->id, use_case_table[usecase->id],
3735 out->usecase, use_case_table[out->usecase]);
3736 select_devices(adev, usecase->id);
3737 }
3738 }
3739
Garmond Leung5fd0b552018-04-17 11:56:12 -07003740 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003741 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 return ret;
3743}
3744
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003745struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3746 unsigned int flags, unsigned int pcm_open_retry_count,
3747 struct pcm_config *config)
3748{
3749 struct pcm* pcm = NULL;
3750
3751 while (1) {
3752 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3753 if (pcm == NULL || !pcm_is_ready(pcm)) {
3754 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3755 if (pcm != NULL) {
3756 pcm_close(pcm);
3757 pcm = NULL;
3758 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003759 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003760 return NULL;
3761
Weiyin Jiang72197252019-10-09 11:49:32 +08003762 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003763 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3764 continue;
3765 }
3766 break;
3767 }
3768
3769 if (pcm_is_ready(pcm)) {
3770 int ret = pcm_prepare(pcm);
3771 if (ret < 0) {
3772 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3773 pcm_close(pcm);
3774 pcm = NULL;
3775 }
3776 }
3777
3778 return pcm;
3779}
3780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781int start_output_stream(struct stream_out *out)
3782{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784 struct audio_usecase *uc_info;
3785 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003786 char mixer_ctl_name[128];
3787 struct mixer_ctl *ctl = NULL;
3788 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303789 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003790 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791
Haynes Mathew George380745d2017-10-04 15:27:45 -07003792 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003793 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3794 ret = -EINVAL;
3795 goto error_config;
3796 }
3797
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003798 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303799 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003800 get_device_types(&out->device_list), is_haptic_usecase);
3801
3802 bool is_speaker_active = compare_device_type(&out->device_list,
3803 AUDIO_DEVICE_OUT_SPEAKER);
3804 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3805 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303806
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303807 if (CARD_STATUS_OFFLINE == out->card_status ||
3808 CARD_STATUS_OFFLINE == adev->card_status) {
3809 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303810 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003811 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303812 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303813
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003814 //Update incall music usecase to reflect correct voice session
3815 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3816 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3817 if (ret != 0) {
3818 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3819 __func__, ret);
3820 goto error_config;
3821 }
3822 }
3823
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003824 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003825 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003826 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303827 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303828 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303829 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3830 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3831 ret = -EAGAIN;
3832 goto error_config;
3833 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303834 }
3835 }
3836 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003837 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303838 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003839 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303840 //combo usecase just by pass a2dp
3841 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003842 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303843 } else {
3844 ALOGE("%s: SCO profile is not ready, return error", __func__);
3845 ret = -EAGAIN;
3846 goto error_config;
3847 }
3848 }
3849 }
3850
Eric Laurentb23d5282013-05-14 15:27:20 -07003851 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852 if (out->pcm_device_id < 0) {
3853 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3854 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003855 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003856 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857 }
3858
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003859 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003860 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3861 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003862 if (adev->haptic_pcm_device_id < 0) {
3863 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3864 __func__, adev->haptic_pcm_device_id, out->usecase);
3865 ret = -EINVAL;
3866 goto error_config;
3867 }
3868 }
3869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003871
3872 if (!uc_info) {
3873 ret = -ENOMEM;
3874 goto error_config;
3875 }
3876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877 uc_info->id = out->usecase;
3878 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003879 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003880 list_init(&uc_info->device_list);
3881 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003882 uc_info->in_snd_device = SND_DEVICE_NONE;
3883 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003884
3885 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003886 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003887 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3888 /* USB backend is not reopened immediately.
3889 This is eventually done as part of select_devices */
3890 }
3891
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003892 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003893
Wei Wangf7ca6c92017-11-21 14:51:20 -08003894 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303895 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3896 adev->perf_lock_opts,
3897 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303898
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003899 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303900 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303901 if (audio_extn_passthru_is_enabled() &&
3902 audio_extn_passthru_is_passthrough_stream(out)) {
3903 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303904 }
3905 }
3906
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003907 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003908 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303909 if (!a2dp_combo) {
3910 check_a2dp_restore_l(adev, out, false);
3911 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003912 struct listnode dev;
3913 list_init(&dev);
3914 assign_devices(&dev, &out->device_list);
3915 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3916 reassign_device_list(&out->device_list,
3917 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003918 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003919 reassign_device_list(&out->device_list,
3920 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303921 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003922 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303923 }
3924 } else {
3925 select_devices(adev, out->usecase);
3926 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003927
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003928 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3929 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003930 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003931 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003932
Derek Chenea197282019-01-07 17:35:01 -08003933 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3934 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003935
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003936 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3937 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003938
3939 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003940 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003941 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3942 ALOGE("%s: pcm stream not ready", __func__);
3943 goto error_open;
3944 }
3945 ret = pcm_start(out->pcm);
3946 if (ret < 0) {
3947 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3948 goto error_open;
3949 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003950 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003951 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003952 unsigned int flags = PCM_OUT;
3953 unsigned int pcm_open_retry_count = 0;
3954 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3955 flags |= PCM_MMAP | PCM_NOIRQ;
3956 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003957 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003958 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003959 } else
3960 flags |= PCM_MONOTONIC;
3961
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003962 if ((adev->vr_audio_mode_enabled) &&
3963 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3964 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3965 "PCM_Dev %d Topology", out->pcm_device_id);
3966 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3967 if (!ctl) {
3968 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3969 __func__, mixer_ctl_name);
3970 } else {
3971 //if success use ULLPP
3972 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3973 __func__, mixer_ctl_name, out->pcm_device_id);
3974 //There is a still a possibility that some sessions
3975 // that request for FAST|RAW when 3D audio is active
3976 //can go through ULLPP. Ideally we expects apps to
3977 //listen to audio focus and stop concurrent playback
3978 //Also, we will look for mode flag (voice_in_communication)
3979 //before enabling the realtime flag.
3980 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3981 }
3982 }
3983
Surendar Karka91fa3682018-07-02 18:12:12 +05303984 if (out->realtime)
3985 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3986 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3987
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003988 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3989 flags, pcm_open_retry_count,
3990 &(out->config));
3991 if (out->pcm == NULL) {
3992 ret = -EIO;
3993 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003994 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003995
3996 if (is_haptic_usecase) {
3997 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3998 adev->haptic_pcm_device_id,
3999 flags, pcm_open_retry_count,
4000 &(adev->haptics_config));
4001 // failure to open haptics pcm shouldnt stop audio,
4002 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004003
4004 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4005 ALOGD("%s: enable haptic audio synchronization", __func__);
4006 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4007 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004008 }
4009
Surendar Karka91fa3682018-07-02 18:12:12 +05304010 if (!out->realtime)
4011 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304012 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004013
Zhou Song2b8f28f2017-09-11 10:51:38 +08004014 // apply volume for voip playback after path is set up
4015 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4016 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304017 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4018 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304019 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4020 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004021 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4022 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304023 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004024 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004025 /*
4026 * set custom channel map if:
4027 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4028 * 2. custom channel map has been set by client
4029 * else default channel map of FC/FR/FL can always be set to DSP
4030 */
4031 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4032 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4033 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004034 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4035 adev->dsp_bit_width_enforce_mode,
4036 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004038 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004039 out->compr = compress_open(adev->snd_card,
4040 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004041 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004042 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304043 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304044 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4045 adev->card_status = CARD_STATUS_OFFLINE;
4046 out->card_status = CARD_STATUS_OFFLINE;
4047 ret = -EIO;
4048 goto error_open;
4049 }
4050
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004051 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004052 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004053 compress_close(out->compr);
4054 out->compr = NULL;
4055 ret = -EIO;
4056 goto error_open;
4057 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304058 /* compress_open sends params of the track, so reset the flag here */
4059 out->is_compr_metadata_avail = false;
4060
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004061 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004062 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004063
Fred Oh3f43e742015-03-04 18:42:34 -08004064 /* Since small bufs uses blocking writes, a write will be blocked
4065 for the default max poll time (20s) in the event of an SSR.
4066 Reduce the poll time to observe and deal with SSR faster.
4067 */
Ashish Jain5106d362016-05-11 19:23:33 +05304068 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004069 compress_set_max_poll_wait(out->compr, 1000);
4070 }
4071
Manish Dewangan69426c82017-01-30 17:35:36 +05304072 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304073 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304074
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004075 audio_extn_dts_create_state_notifier_node(out->usecase);
4076 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4077 popcount(out->channel_mask),
4078 out->playback_started);
4079
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004080#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304081 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004082 audio_extn_dolby_send_ddp_endp_params(adev);
4083#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304084 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4085 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004086 if (adev->visualizer_start_output != NULL)
4087 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4088 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304089 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004090 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004091 }
Derek Chenf13dd492018-11-13 14:53:51 -08004092
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004093 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004094 /* Update cached volume from media to offload/direct stream */
4095 struct listnode *node = NULL;
4096 list_for_each(node, &adev->active_outputs_list) {
4097 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4098 streams_output_ctxt_t,
4099 list);
4100 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4101 out->volume_l = out_ctxt->output->volume_l;
4102 out->volume_r = out_ctxt->output->volume_r;
4103 }
4104 }
4105 out_set_compr_volume(&out->stream,
4106 out->volume_l, out->volume_r);
4107 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004109
4110 if (ret == 0) {
4111 register_out_stream(out);
4112 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004113 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4114 ALOGE("%s: pcm stream not ready", __func__);
4115 goto error_open;
4116 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004117 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004118 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004119 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004120 if (ret < 0)
4121 goto error_open;
4122 }
4123 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004124 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304125 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004126 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004127
vivek mehtad15d2bf2019-05-17 13:35:10 -07004128 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4129 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4130 audio_low_latency_hint_start();
4131 }
4132
Manish Dewangan21a850a2017-08-14 12:03:55 +05304133 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004134 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004135 if (ret < 0)
4136 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4137 }
4138
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004139 // consider a scenario where on pause lower layers are tear down.
4140 // so on resume, swap mixer control need to be sent only when
4141 // backend is active, hence rather than sending from enable device
4142 // sending it from start of streamtream
4143
4144 platform_set_swap_channels(adev, true);
4145
Haynes Mathew George380745d2017-10-04 15:27:45 -07004146 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304147 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004148 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004149error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004150 if (adev->haptic_pcm) {
4151 pcm_close(adev->haptic_pcm);
4152 adev->haptic_pcm = NULL;
4153 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004154 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304155 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004157error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304158 /*
4159 * sleep 50ms to allow sufficient time for kernel
4160 * drivers to recover incases like SSR.
4161 */
4162 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004163error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004164 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304165 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004166 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167}
4168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004169static int check_input_parameters(uint32_t sample_rate,
4170 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004171 int channel_count,
4172 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004174 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004175
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304176 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4177 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4178 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004179 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004180 !audio_extn_compr_cap_format_supported(format) &&
4181 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004182 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004183
Aalique Grahame22e49102018-12-18 14:23:57 -08004184 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4185 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4186 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4187 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4188 return -EINVAL;
4189 }
4190
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004191 switch (channel_count) {
4192 case 1:
4193 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304194 case 3:
4195 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004196 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004197 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304198 case 10:
4199 case 12:
4200 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004201 break;
4202 default:
4203 ret = -EINVAL;
4204 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004205
4206 switch (sample_rate) {
4207 case 8000:
4208 case 11025:
4209 case 12000:
4210 case 16000:
4211 case 22050:
4212 case 24000:
4213 case 32000:
4214 case 44100:
4215 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004216 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304217 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004218 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304219 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220 break;
4221 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004222 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223 }
4224
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004225 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226}
4227
Naresh Tanniru04f71882018-06-26 17:46:22 +05304228
4229/** Add a value in a list if not already present.
4230 * @return true if value was successfully inserted or already present,
4231 * false if the list is full and does not contain the value.
4232 */
4233static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4234 for (size_t i = 0; i < list_length; i++) {
4235 if (list[i] == value) return true; // value is already present
4236 if (list[i] == 0) { // no values in this slot
4237 list[i] = value;
4238 return true; // value inserted
4239 }
4240 }
4241 return false; // could not insert value
4242}
4243
4244/** Add channel_mask in supported_channel_masks if not already present.
4245 * @return true if channel_mask was successfully inserted or already present,
4246 * false if supported_channel_masks is full and does not contain channel_mask.
4247 */
4248static void register_channel_mask(audio_channel_mask_t channel_mask,
4249 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4250 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4251 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4252}
4253
4254/** Add format in supported_formats if not already present.
4255 * @return true if format was successfully inserted or already present,
4256 * false if supported_formats is full and does not contain format.
4257 */
4258static void register_format(audio_format_t format,
4259 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4260 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4261 "%s: stream can not declare supporting its format %x", __func__, format);
4262}
4263/** Add sample_rate in supported_sample_rates if not already present.
4264 * @return true if sample_rate was successfully inserted or already present,
4265 * false if supported_sample_rates is full and does not contain sample_rate.
4266 */
4267static void register_sample_rate(uint32_t sample_rate,
4268 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4269 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4270 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4271}
4272
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004273static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4274{
4275 uint32_t high = num1, low = num2, temp = 0;
4276
4277 if (!num1 || !num2)
4278 return 0;
4279
4280 if (num1 < num2) {
4281 high = num2;
4282 low = num1;
4283 }
4284
4285 while (low != 0) {
4286 temp = low;
4287 low = high % low;
4288 high = temp;
4289 }
4290 return (num1 * num2)/high;
4291}
4292
4293static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4294{
4295 uint32_t remainder = 0;
4296
4297 if (!multiplier)
4298 return num;
4299
4300 remainder = num % multiplier;
4301 if (remainder)
4302 num += (multiplier - remainder);
4303
4304 return num;
4305}
4306
Aalique Grahame22e49102018-12-18 14:23:57 -08004307static size_t get_stream_buffer_size(size_t duration_ms,
4308 uint32_t sample_rate,
4309 audio_format_t format,
4310 int channel_count,
4311 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004312{
4313 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004314 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004315
Aalique Grahame22e49102018-12-18 14:23:57 -08004316 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004317 if (is_low_latency)
4318 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304319
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004320 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004321 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322
Ralf Herzbd08d632018-09-28 15:50:49 +02004323 /* make sure the size is multiple of 32 bytes and additionally multiple of
4324 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004325 * At 48 kHz mono 16-bit PCM:
4326 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4327 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004328 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004329 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004330 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004331
4332 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333}
4334
Aalique Grahame22e49102018-12-18 14:23:57 -08004335static size_t get_input_buffer_size(uint32_t sample_rate,
4336 audio_format_t format,
4337 int channel_count,
4338 bool is_low_latency)
4339{
4340 /* Don't know if USB HIFI in this context so use true to be conservative */
4341 if (check_input_parameters(sample_rate, format, channel_count,
4342 true /*is_usb_hifi */) != 0)
4343 return 0;
4344
4345 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4346 sample_rate,
4347 format,
4348 channel_count,
4349 is_low_latency);
4350}
4351
Derek Chenf6318be2017-06-12 17:16:24 -04004352size_t get_output_period_size(uint32_t sample_rate,
4353 audio_format_t format,
4354 int channel_count,
4355 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304356{
4357 size_t size = 0;
4358 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4359
4360 if ((duration == 0) || (sample_rate == 0) ||
4361 (bytes_per_sample == 0) || (channel_count == 0)) {
4362 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4363 bytes_per_sample, channel_count);
4364 return -EINVAL;
4365 }
4366
4367 size = (sample_rate *
4368 duration *
4369 bytes_per_sample *
4370 channel_count) / 1000;
4371 /*
4372 * To have same PCM samples for all channels, the buffer size requires to
4373 * be multiple of (number of channels * bytes per sample)
4374 * For writes to succeed, the buffer must be written at address which is multiple of 32
4375 */
4376 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4377
4378 return (size/(channel_count * bytes_per_sample));
4379}
4380
Zhou Song48453a02018-01-10 17:50:59 +08004381static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304382{
4383 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004384 uint64_t written_frames = 0;
4385 uint64_t kernel_frames = 0;
4386 uint64_t dsp_frames = 0;
4387 uint64_t signed_frames = 0;
4388 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304389
4390 /* This adjustment accounts for buffering after app processor.
4391 * It is based on estimated DSP latency per use case, rather than exact.
4392 */
Robert Lee58215542019-07-15 20:55:12 +08004393 pthread_mutex_lock(&adev->lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004394 dsp_frames = platform_render_latency(out->dev, out->usecase) *
4395 out->sample_rate / 1000000LL;
Robert Lee58215542019-07-15 20:55:12 +08004396 pthread_mutex_unlock(&adev->lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304397
Zhou Song48453a02018-01-10 17:50:59 +08004398 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004399 written_frames = out->written /
4400 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4401
Ashish Jain5106d362016-05-11 19:23:33 +05304402 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4403 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4404 * hence only estimate.
4405 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004406 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4407 kernel_frames = kernel_buffer_size /
4408 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304409
Weiyin Jiang4813da12020-05-28 00:37:28 +08004410 if (written_frames >= (kernel_frames + dsp_frames))
4411 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304412
Zhou Song48453a02018-01-10 17:50:59 +08004413 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304414 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004415 if (timestamp != NULL )
4416 *timestamp = out->writeAt;
4417 } else if (timestamp != NULL) {
4418 clock_gettime(CLOCK_MONOTONIC, timestamp);
4419 }
4420 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304421
Weiyin Jiang4813da12020-05-28 00:37:28 +08004422 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4423 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304424
4425 return actual_frames_rendered;
4426}
4427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004428static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4429{
4430 struct stream_out *out = (struct stream_out *)stream;
4431
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004432 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004433}
4434
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004435static int out_set_sample_rate(struct audio_stream *stream __unused,
4436 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004437{
4438 return -ENOSYS;
4439}
4440
4441static size_t out_get_buffer_size(const struct audio_stream *stream)
4442{
4443 struct stream_out *out = (struct stream_out *)stream;
4444
Varun Balaraje49253e2017-07-06 19:48:56 +05304445 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304446 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304447 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304448 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4449 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4450 else
4451 return out->compr_config.fragment_size;
4452 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004453 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304454 else if (is_offload_usecase(out->usecase) &&
4455 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304456 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004457
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004458 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004459 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004460}
4461
4462static uint32_t out_get_channels(const struct audio_stream *stream)
4463{
4464 struct stream_out *out = (struct stream_out *)stream;
4465
4466 return out->channel_mask;
4467}
4468
4469static audio_format_t out_get_format(const struct audio_stream *stream)
4470{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004471 struct stream_out *out = (struct stream_out *)stream;
4472
4473 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004474}
4475
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004476static int out_set_format(struct audio_stream *stream __unused,
4477 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004478{
4479 return -ENOSYS;
4480}
4481
4482static int out_standby(struct audio_stream *stream)
4483{
4484 struct stream_out *out = (struct stream_out *)stream;
4485 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004486 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004487
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304488 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4489 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004490
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004491 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004492 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004493 if (adev->adm_deregister_stream)
4494 adev->adm_deregister_stream(adev->adm_data, out->handle);
4495
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004496 if (is_offload_usecase(out->usecase))
4497 stop_compressed_output_l(out);
4498
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004499 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004501 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4502 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304503 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004504 pthread_mutex_unlock(&adev->lock);
4505 pthread_mutex_unlock(&out->lock);
4506 ALOGD("VOIP output entered standby");
4507 return 0;
4508 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004509 if (out->pcm) {
4510 pcm_close(out->pcm);
4511 out->pcm = NULL;
4512 }
Meng Wanga09da002020-04-20 12:56:04 +08004513 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4514 if (adev->haptic_pcm) {
4515 pcm_close(adev->haptic_pcm);
4516 adev->haptic_pcm = NULL;
4517 }
4518
4519 if (adev->haptic_buffer != NULL) {
4520 free(adev->haptic_buffer);
4521 adev->haptic_buffer = NULL;
4522 adev->haptic_buffer_size = 0;
4523 }
4524 adev->haptic_pcm_device_id = 0;
4525 }
4526
Haynes Mathew George16081042017-05-31 17:16:49 -07004527 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4528 do_stop = out->playback_started;
4529 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004530
4531 if (out->mmap_shared_memory_fd >= 0) {
4532 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4533 __func__, out->mmap_shared_memory_fd);
4534 close(out->mmap_shared_memory_fd);
4535 out->mmap_shared_memory_fd = -1;
4536 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004537 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004538 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004539 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304540 out->send_next_track_params = false;
4541 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004542 out->gapless_mdata.encoder_delay = 0;
4543 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004544 if (out->compr != NULL) {
4545 compress_close(out->compr);
4546 out->compr = NULL;
4547 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004548 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004549 if (do_stop) {
4550 stop_output_stream(out);
4551 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304552 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004553 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004554 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004555 }
4556 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304557 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004558 return 0;
4559}
4560
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304561static int out_on_error(struct audio_stream *stream)
4562{
4563 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004564 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304565
4566 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004567 // always send CMD_ERROR for offload streams, this
4568 // is needed e.g. when SSR happens within compress_open
4569 // since the stream is active, offload_callback_thread is also active.
4570 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4571 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004572 }
4573 pthread_mutex_unlock(&out->lock);
4574
4575 status = out_standby(&out->stream.common);
4576
4577 lock_output_stream(out);
4578 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004579 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304580 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304581
4582 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4583 ALOGD("Setting previous card status if offline");
4584 out->prev_card_status_offline = true;
4585 }
4586
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304587 pthread_mutex_unlock(&out->lock);
4588
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004589 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304590}
4591
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304592/*
4593 *standby implementation without locks, assumes that the callee already
4594 *has taken adev and out lock.
4595 */
4596int out_standby_l(struct audio_stream *stream)
4597{
4598 struct stream_out *out = (struct stream_out *)stream;
4599 struct audio_device *adev = out->dev;
4600
4601 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4602 stream, out->usecase, use_case_table[out->usecase]);
4603
4604 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004605 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304606 if (adev->adm_deregister_stream)
4607 adev->adm_deregister_stream(adev->adm_data, out->handle);
4608
4609 if (is_offload_usecase(out->usecase))
4610 stop_compressed_output_l(out);
4611
4612 out->standby = true;
4613 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4614 voice_extn_compress_voip_close_output_stream(stream);
4615 out->started = 0;
4616 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004617 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304618 return 0;
4619 } else if (!is_offload_usecase(out->usecase)) {
4620 if (out->pcm) {
4621 pcm_close(out->pcm);
4622 out->pcm = NULL;
4623 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004624 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4625 if (adev->haptic_pcm) {
4626 pcm_close(adev->haptic_pcm);
4627 adev->haptic_pcm = NULL;
4628 }
4629
4630 if (adev->haptic_buffer != NULL) {
4631 free(adev->haptic_buffer);
4632 adev->haptic_buffer = NULL;
4633 adev->haptic_buffer_size = 0;
4634 }
4635 adev->haptic_pcm_device_id = 0;
4636 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304637 } else {
4638 ALOGD("copl(%p):standby", out);
4639 out->send_next_track_params = false;
4640 out->is_compr_metadata_avail = false;
4641 out->gapless_mdata.encoder_delay = 0;
4642 out->gapless_mdata.encoder_padding = 0;
4643 if (out->compr != NULL) {
4644 compress_close(out->compr);
4645 out->compr = NULL;
4646 }
4647 }
4648 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004649 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304650 }
4651 ALOGD("%s: exit", __func__);
4652 return 0;
4653}
4654
Aalique Grahame22e49102018-12-18 14:23:57 -08004655static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656{
Aalique Grahame22e49102018-12-18 14:23:57 -08004657 struct stream_out *out = (struct stream_out *)stream;
4658
4659 // We try to get the lock for consistency,
4660 // but it isn't necessary for these variables.
4661 // If we're not in standby, we may be blocked on a write.
4662 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4663 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4664 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4665
Andy Hunga1f48fa2019-07-01 18:14:53 -07004666 char buffer[256]; // for statistics formatting
4667 if (!is_offload_usecase(out->usecase)) {
4668 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4669 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4670 }
4671
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004672 if (out->start_latency_ms.n > 0) {
4673 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4674 dprintf(fd, " Start latency ms: %s\n", buffer);
4675 }
4676
Aalique Grahame22e49102018-12-18 14:23:57 -08004677 if (locked) {
4678 pthread_mutex_unlock(&out->lock);
4679 }
4680
4681 // dump error info
4682 (void)error_log_dump(
4683 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685 return 0;
4686}
4687
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004688static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4689{
4690 int ret = 0;
4691 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004692
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004693 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004694 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004695 return -EINVAL;
4696 }
4697
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304698 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004699
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004700 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4701 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304702 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004703 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004704 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4705 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304706 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004707 }
4708
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004709 ALOGV("%s new encoder delay %u and padding %u", __func__,
4710 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4711
4712 return 0;
4713}
4714
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004715static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4716{
4717 return out == adev->primary_output || out == adev->voice_tx_output;
4718}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004719
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304720// note: this call is safe only if the stream_cb is
4721// removed first in close_output_stream (as is done now).
4722static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4723{
4724 if (!stream || !parms)
4725 return;
4726
4727 struct stream_out *out = (struct stream_out *)stream;
4728 struct audio_device *adev = out->dev;
4729
4730 card_status_t status;
4731 int card;
4732 if (parse_snd_card_status(parms, &card, &status) < 0)
4733 return;
4734
4735 pthread_mutex_lock(&adev->lock);
4736 bool valid_cb = (card == adev->snd_card);
4737 pthread_mutex_unlock(&adev->lock);
4738
4739 if (!valid_cb)
4740 return;
4741
4742 lock_output_stream(out);
4743 if (out->card_status != status)
4744 out->card_status = status;
4745 pthread_mutex_unlock(&out->lock);
4746
4747 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4748 use_case_table[out->usecase],
4749 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4750
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304751 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304752 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304753 if (voice_is_call_state_active(adev) &&
4754 out == adev->primary_output) {
4755 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4756 pthread_mutex_lock(&adev->lock);
4757 voice_stop_call(adev);
4758 adev->mode = AUDIO_MODE_NORMAL;
4759 pthread_mutex_unlock(&adev->lock);
4760 }
4761 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304762 return;
4763}
4764
Kevin Rocardfce19002017-08-07 19:21:36 -07004765static int get_alive_usb_card(struct str_parms* parms) {
4766 int card;
4767 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4768 !audio_extn_usb_alive(card)) {
4769 return card;
4770 }
4771 return -ENODEV;
4772}
4773
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004774int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004775 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004776{
4777 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004778 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004779 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004780 bool bypass_a2dp = false;
4781 bool reconfig = false;
4782 unsigned long service_interval = 0;
4783
4784 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004785 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4786
4787 list_init(&new_devices);
4788 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004789
4790 lock_output_stream(out);
4791 pthread_mutex_lock(&adev->lock);
4792
4793 /*
4794 * When HDMI cable is unplugged the music playback is paused and
4795 * the policy manager sends routing=0. But the audioflinger continues
4796 * to write data until standby time (3sec). As the HDMI core is
4797 * turned off, the write gets blocked.
4798 * Avoid this by routing audio to speaker until standby.
4799 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004800 if (is_single_device_type_equal(&out->device_list,
4801 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004802 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004803 !audio_extn_passthru_is_passthrough_stream(out) &&
4804 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
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 A2DP is disconnected the
4809 * music playback is paused and the policy manager sends routing=0
4810 * But the audioflinger continues to write data until standby time
4811 * (3sec). As BT is turned off, the write gets blocked.
4812 * Avoid this by routing audio to speaker until standby.
4813 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004814 if (is_a2dp_out_device_type(&out->device_list) &&
4815 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004816 !audio_extn_a2dp_source_is_ready() &&
4817 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004818 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004819 }
4820 /*
4821 * When USB headset is disconnected the music platback paused
4822 * and the policy manager send routing=0. But if the USB is connected
4823 * back before the standby time, AFE is not closed and opened
4824 * when USB is connected back. So routing to speker will guarantee
4825 * AFE reconfiguration and AFE will be opend once USB is connected again
4826 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004827 if (is_usb_out_device_type(&out->device_list) &&
4828 list_empty(&new_devices) &&
4829 !audio_extn_usb_connected(NULL)) {
4830 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4831 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004832 /* To avoid a2dp to sco overlapping / BT device improper state
4833 * check with BT lib about a2dp streaming support before routing
4834 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004835 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004836 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004837 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4838 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004839 //combo usecase just by pass a2dp
4840 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4841 bypass_a2dp = true;
4842 } else {
4843 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4844 /* update device to a2dp and don't route as BT returned error
4845 * However it is still possible a2dp routing called because
4846 * of current active device disconnection (like wired headset)
4847 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004848 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004849 pthread_mutex_unlock(&adev->lock);
4850 pthread_mutex_unlock(&out->lock);
4851 goto error;
4852 }
4853 }
4854 }
4855
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004856 // Workaround: If routing to an non existing usb device, fail gracefully
4857 // The routing request will otherwise block during 10 second
4858 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004859 if (is_usb_out_device_type(&new_devices)) {
4860 struct str_parms *parms =
4861 str_parms_create_str(get_usb_device_address(&new_devices));
4862 if (!parms)
4863 goto error;
4864 if ((card = get_alive_usb_card(parms)) >= 0) {
4865 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4866 pthread_mutex_unlock(&adev->lock);
4867 pthread_mutex_unlock(&out->lock);
4868 str_parms_destroy(parms);
4869 ret = -ENOSYS;
4870 goto error;
4871 }
4872 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004873 }
4874
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004875 // Workaround: If routing to an non existing hdmi device, fail gracefully
4876 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4877 (platform_get_edid_info_v2(adev->platform,
4878 out->extconn.cs.controller,
4879 out->extconn.cs.stream) != 0)) {
4880 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4881 pthread_mutex_unlock(&adev->lock);
4882 pthread_mutex_unlock(&out->lock);
4883 ret = -ENOSYS;
4884 goto error;
4885 }
4886
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004887 /*
4888 * select_devices() call below switches all the usecases on the same
4889 * backend to the new device. Refer to check_usecases_codec_backend() in
4890 * the select_devices(). But how do we undo this?
4891 *
4892 * For example, music playback is active on headset (deep-buffer usecase)
4893 * and if we go to ringtones and select a ringtone, low-latency usecase
4894 * will be started on headset+speaker. As we can't enable headset+speaker
4895 * and headset devices at the same time, select_devices() switches the music
4896 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4897 * So when the ringtone playback is completed, how do we undo the same?
4898 *
4899 * We are relying on the out_set_parameters() call on deep-buffer output,
4900 * once the ringtone playback is ended.
4901 * NOTE: We should not check if the current devices are same as new devices.
4902 * Because select_devices() must be called to switch back the music
4903 * playback to headset.
4904 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004905 if (!list_empty(&new_devices)) {
4906 bool same_dev = compare_devices(&out->device_list, &new_devices);
4907 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004908
4909 if (output_drives_call(adev, out)) {
4910 if (!voice_is_call_state_active(adev)) {
4911 if (adev->mode == AUDIO_MODE_IN_CALL) {
4912 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004913 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004914 service_interval =
4915 audio_extn_usb_find_service_interval(true, true /*playback*/);
4916 audio_extn_usb_set_service_interval(true /*playback*/,
4917 service_interval,
4918 &reconfig);
4919 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4920 }
4921 ret = voice_start_call(adev);
4922 }
4923 } else {
4924 adev->current_call_output = out;
4925 voice_update_devices_for_all_voice_usecases(adev);
4926 }
4927 }
4928
4929 if (!out->standby) {
4930 if (!same_dev) {
4931 ALOGV("update routing change");
4932 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4933 adev->perf_lock_opts,
4934 adev->perf_lock_opts_size);
4935 if (adev->adm_on_routing_change)
4936 adev->adm_on_routing_change(adev->adm_data,
4937 out->handle);
4938 }
4939 if (!bypass_a2dp) {
4940 select_devices(adev, out->usecase);
4941 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004942 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4943 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004944 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004945 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004946 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004947 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004948 }
4949
4950 if (!same_dev) {
4951 // on device switch force swap, lower functions will make sure
4952 // to check if swap is allowed or not.
4953 platform_set_swap_channels(adev, true);
4954 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4955 }
4956 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4957 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004958 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004959 pthread_mutex_lock(&out->compr_mute_lock);
4960 out->a2dp_compress_mute = false;
4961 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4962 pthread_mutex_unlock(&out->compr_mute_lock);
4963 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4964 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4965 }
4966 }
4967 }
4968
4969 pthread_mutex_unlock(&adev->lock);
4970 pthread_mutex_unlock(&out->lock);
4971
4972 /*handles device and call state changes*/
4973 audio_extn_extspk_update(adev->extspk);
4974
4975error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004976 ALOGV("%s: exit: code(%d)", __func__, ret);
4977 return ret;
4978}
4979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004980static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4981{
4982 struct stream_out *out = (struct stream_out *)stream;
4983 struct audio_device *adev = out->dev;
4984 struct str_parms *parms;
4985 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004986 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004987 int ext_controller = -1;
4988 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004989
sangwoobc677242013-08-08 16:53:43 +09004990 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004991 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004992 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304993 if (!parms)
4994 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004995
4996 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4997 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08004998 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004999 out->extconn.cs.controller = ext_controller;
5000 out->extconn.cs.stream = ext_stream;
5001 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5002 use_case_table[out->usecase], out->extconn.cs.controller,
5003 out->extconn.cs.stream);
5004 }
5005
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005006 if (out == adev->primary_output) {
5007 pthread_mutex_lock(&adev->lock);
5008 audio_extn_set_parameters(adev, parms);
5009 pthread_mutex_unlock(&adev->lock);
5010 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005011 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005012 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005013 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005014
5015 audio_extn_dts_create_state_notifier_node(out->usecase);
5016 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5017 popcount(out->channel_mask),
5018 out->playback_started);
5019
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005020 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005021 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005022
Surendar Karkaf51b5842018-04-26 11:28:38 +05305023 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5024 sizeof(value));
5025 if (err >= 0) {
5026 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5027 audio_extn_send_dual_mono_mixing_coefficients(out);
5028 }
5029
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305030 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5031 if (err >= 0) {
5032 strlcpy(out->profile, value, sizeof(out->profile));
5033 ALOGV("updating stream profile with value '%s'", out->profile);
5034 lock_output_stream(out);
5035 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5036 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005037 &out->device_list, out->flags,
5038 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305039 out->sample_rate, out->bit_width,
5040 out->channel_mask, out->profile,
5041 &out->app_type_cfg);
5042 pthread_mutex_unlock(&out->lock);
5043 }
5044
Alexy Joseph98988832017-01-13 14:56:59 -08005045 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005046 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5047 // and vendor.audio.hal.output.suspend.supported is set to true
5048 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005049 //check suspend parameter only for low latency and if the property
5050 //is enabled
5051 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5052 ALOGI("%s: got suspend_playback %s", __func__, value);
5053 lock_output_stream(out);
5054 if (!strncmp(value, "false", 5)) {
5055 //suspend_playback=false is supposed to set QOS value back to 75%
5056 //the mixer control sent with value Enable will achieve that
5057 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5058 } else if (!strncmp (value, "true", 4)) {
5059 //suspend_playback=true is supposed to remove QOS value
5060 //resetting the mixer control will set the default value
5061 //for the mixer control which is Disable and this removes the QOS vote
5062 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5063 } else {
5064 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5065 " got %s", __func__, value);
5066 ret = -1;
5067 }
5068
5069 if (ret != 0) {
5070 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5071 __func__, out->pm_qos_mixer_path, ret);
5072 }
5073
5074 pthread_mutex_unlock(&out->lock);
5075 }
5076 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005077
Alexy Joseph98988832017-01-13 14:56:59 -08005078 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005079 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305080error:
Eric Laurent994a6932013-07-17 11:51:42 -07005081 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005082 return ret;
5083}
5084
Paul McLeana50b7332018-12-17 08:24:21 -07005085static int in_set_microphone_direction(const struct audio_stream_in *stream,
5086 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005087 struct stream_in *in = (struct stream_in *)stream;
5088
5089 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5090
5091 in->direction = dir;
5092
5093 if (in->standby)
5094 return 0;
5095
5096 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005097}
5098
5099static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005100 struct stream_in *in = (struct stream_in *)stream;
5101
5102 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5103
5104 if (zoom > 1.0 || zoom < -1.0)
5105 return -EINVAL;
5106
5107 in->zoom = zoom;
5108
5109 if (in->standby)
5110 return 0;
5111
5112 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005113}
5114
5115
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005116static bool stream_get_parameter_channels(struct str_parms *query,
5117 struct str_parms *reply,
5118 audio_channel_mask_t *supported_channel_masks) {
5119 int ret = -1;
5120 char value[512];
5121 bool first = true;
5122 size_t i, j;
5123
5124 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5125 ret = 0;
5126 value[0] = '\0';
5127 i = 0;
5128 while (supported_channel_masks[i] != 0) {
5129 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5130 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5131 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305132 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005133
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305134 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005135 first = false;
5136 break;
5137 }
5138 }
5139 i++;
5140 }
5141 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5142 }
5143 return ret == 0;
5144}
5145
5146static bool stream_get_parameter_formats(struct str_parms *query,
5147 struct str_parms *reply,
5148 audio_format_t *supported_formats) {
5149 int ret = -1;
5150 char value[256];
5151 size_t i, j;
5152 bool first = true;
5153
5154 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5155 ret = 0;
5156 value[0] = '\0';
5157 i = 0;
5158 while (supported_formats[i] != 0) {
5159 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5160 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5161 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305162 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005163 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305164 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005165 first = false;
5166 break;
5167 }
5168 }
5169 i++;
5170 }
5171 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5172 }
5173 return ret == 0;
5174}
5175
5176static bool stream_get_parameter_rates(struct str_parms *query,
5177 struct str_parms *reply,
5178 uint32_t *supported_sample_rates) {
5179
5180 int i;
5181 char value[256];
5182 int ret = -1;
5183 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5184 ret = 0;
5185 value[0] = '\0';
5186 i=0;
5187 int cursor = 0;
5188 while (supported_sample_rates[i]) {
5189 int avail = sizeof(value) - cursor;
5190 ret = snprintf(value + cursor, avail, "%s%d",
5191 cursor > 0 ? "|" : "",
5192 supported_sample_rates[i]);
5193 if (ret < 0 || ret >= avail) {
5194 // if cursor is at the last element of the array
5195 // overwrite with \0 is duplicate work as
5196 // snprintf already put a \0 in place.
5197 // else
5198 // we had space to write the '|' at value[cursor]
5199 // (which will be overwritten) or no space to fill
5200 // the first element (=> cursor == 0)
5201 value[cursor] = '\0';
5202 break;
5203 }
5204 cursor += ret;
5205 ++i;
5206 }
5207 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5208 value);
5209 }
5210 return ret >= 0;
5211}
5212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005213static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5214{
5215 struct stream_out *out = (struct stream_out *)stream;
5216 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005217 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005218 char value[256];
5219 struct str_parms *reply = str_parms_create();
5220 size_t i, j;
5221 int ret;
5222 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005223
5224 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005225 if (reply) {
5226 str_parms_destroy(reply);
5227 }
5228 if (query) {
5229 str_parms_destroy(query);
5230 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005231 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5232 return NULL;
5233 }
5234
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005235 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005236 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5237 if (ret >= 0) {
5238 value[0] = '\0';
5239 i = 0;
5240 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005241 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5242 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005243 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005244 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005245 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005246 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005247 first = false;
5248 break;
5249 }
5250 }
5251 i++;
5252 }
5253 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5254 str = str_parms_to_str(reply);
5255 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005256 voice_extn_out_get_parameters(out, query, reply);
5257 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005258 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005259
Alexy Joseph62142aa2015-11-16 15:10:34 -08005260
5261 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5262 if (ret >= 0) {
5263 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305264 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5265 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005266 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305267 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005268 } else {
5269 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305270 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005271 }
5272 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005273 if (str)
5274 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005275 str = str_parms_to_str(reply);
5276 }
5277
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005278 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5279 if (ret >= 0) {
5280 value[0] = '\0';
5281 i = 0;
5282 first = true;
5283 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005284 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5285 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005286 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005287 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005288 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005289 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005290 first = false;
5291 break;
5292 }
5293 }
5294 i++;
5295 }
5296 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005297 if (str)
5298 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005299 str = str_parms_to_str(reply);
5300 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005301
5302 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5303 if (ret >= 0) {
5304 value[0] = '\0';
5305 i = 0;
5306 first = true;
5307 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005308 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5309 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005310 if (!first) {
5311 strlcat(value, "|", sizeof(value));
5312 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005313 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005314 first = false;
5315 break;
5316 }
5317 }
5318 i++;
5319 }
5320 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5321 if (str)
5322 free(str);
5323 str = str_parms_to_str(reply);
5324 }
5325
Alexy Joseph98988832017-01-13 14:56:59 -08005326 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5327 //only low latency track supports suspend_resume
5328 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005329 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005330 if (str)
5331 free(str);
5332 str = str_parms_to_str(reply);
5333 }
5334
5335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005336 str_parms_destroy(query);
5337 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005338 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005339 return str;
5340}
5341
5342static uint32_t out_get_latency(const struct audio_stream_out *stream)
5343{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005344 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005345 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005346 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005347
Alexy Josephaa54c872014-12-03 02:46:47 -08005348 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305349 lock_output_stream(out);
5350 latency = audio_extn_utils_compress_get_dsp_latency(out);
5351 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005352 } else if ((out->realtime) ||
5353 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005354 // since the buffer won't be filled up faster than realtime,
5355 // return a smaller number
5356 if (out->config.rate)
5357 period_ms = (out->af_period_multiplier * out->config.period_size *
5358 1000) / (out->config.rate);
5359 else
5360 period_ms = 0;
Robert Lee58215542019-07-15 20:55:12 +08005361 pthread_mutex_lock(&adev->lock);
5362 latency = period_ms + platform_render_latency(out->dev, out->usecase)/1000;
5363 pthread_mutex_unlock(&adev->lock);
Alexy Josephaa54c872014-12-03 02:46:47 -08005364 } else {
5365 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005366 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005367 }
5368
Zhou Songd2537a02020-06-11 22:04:46 +08005369 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005370 latency += audio_extn_a2dp_get_encoder_latency();
5371
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305372 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005373 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005374}
5375
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305376static float AmpToDb(float amplification)
5377{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305378 float db = DSD_VOLUME_MIN_DB;
5379 if (amplification > 0) {
5380 db = 20 * log10(amplification);
5381 if(db < DSD_VOLUME_MIN_DB)
5382 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305383 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305384 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305385}
5386
Arun Mirpuri5d170872019-03-26 13:21:31 -07005387static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5388 float right)
5389{
5390 struct stream_out *out = (struct stream_out *)stream;
5391 long volume = 0;
5392 char mixer_ctl_name[128] = "";
5393 struct audio_device *adev = out->dev;
5394 struct mixer_ctl *ctl = NULL;
5395 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5396 PCM_PLAYBACK);
5397
5398 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5399 "Playback %d Volume", pcm_device_id);
5400 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5401 if (!ctl) {
5402 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5403 __func__, mixer_ctl_name);
5404 return -EINVAL;
5405 }
5406 if (left != right)
5407 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5408 __func__, left, right);
5409 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5410 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5411 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5412 __func__, mixer_ctl_name, volume);
5413 return -EINVAL;
5414 }
5415 return 0;
5416}
5417
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305418static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5419 float right)
5420{
5421 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305422 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305423 char mixer_ctl_name[128];
5424 struct audio_device *adev = out->dev;
5425 struct mixer_ctl *ctl;
5426 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5427 PCM_PLAYBACK);
5428
5429 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5430 "Compress Playback %d Volume", pcm_device_id);
5431 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5432 if (!ctl) {
5433 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5434 __func__, mixer_ctl_name);
5435 return -EINVAL;
5436 }
5437 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5438 __func__, mixer_ctl_name, left, right);
5439 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5440 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5441 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5442
5443 return 0;
5444}
5445
Zhou Song2b8f28f2017-09-11 10:51:38 +08005446static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5447 float right)
5448{
5449 struct stream_out *out = (struct stream_out *)stream;
5450 char mixer_ctl_name[] = "App Type Gain";
5451 struct audio_device *adev = out->dev;
5452 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305453 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005454
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005455 if (!is_valid_volume(left, right)) {
5456 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5457 __func__, left, right);
5458 return -EINVAL;
5459 }
5460
Zhou Song2b8f28f2017-09-11 10:51:38 +08005461 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5462 if (!ctl) {
5463 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5464 __func__, mixer_ctl_name);
5465 return -EINVAL;
5466 }
5467
5468 set_values[0] = 0; //0: Rx Session 1:Tx Session
5469 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305470 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5471 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005472
5473 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5474 return 0;
5475}
5476
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305477static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5478 float right)
5479{
5480 struct stream_out *out = (struct stream_out *)stream;
5481 /* Volume control for pcm playback */
5482 if (left != right) {
5483 return -EINVAL;
5484 } else {
5485 char mixer_ctl_name[128];
5486 struct audio_device *adev = out->dev;
5487 struct mixer_ctl *ctl;
5488 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5489 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5490 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5491 if (!ctl) {
5492 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5493 return -EINVAL;
5494 }
5495
5496 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5497 int ret = mixer_ctl_set_value(ctl, 0, volume);
5498 if (ret < 0) {
5499 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5500 return -EINVAL;
5501 }
5502
5503 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5504
5505 return 0;
5506 }
5507}
5508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005509static int out_set_volume(struct audio_stream_out *stream, float left,
5510 float right)
5511{
Eric Laurenta9024de2013-04-04 09:19:12 -07005512 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005513 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305514 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005515
Arun Mirpuri5d170872019-03-26 13:21:31 -07005516 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005517 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5518 /* only take left channel into account: the API is for stereo anyway */
5519 out->muted = (left == 0.0f);
5520 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005521 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305522 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005523 /*
5524 * Set mute or umute on HDMI passthrough stream.
5525 * Only take left channel into account.
5526 * Mute is 0 and unmute 1
5527 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305528 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305529 } else if (out->format == AUDIO_FORMAT_DSD){
5530 char mixer_ctl_name[128] = "DSD Volume";
5531 struct audio_device *adev = out->dev;
5532 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5533
5534 if (!ctl) {
5535 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5536 __func__, mixer_ctl_name);
5537 return -EINVAL;
5538 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305539 volume[0] = (long)(AmpToDb(left));
5540 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305541 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5542 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005543 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005544 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005545 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5546 struct listnode *node = NULL;
5547 list_for_each(node, &adev->active_outputs_list) {
5548 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5549 streams_output_ctxt_t,
5550 list);
5551 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5552 out->volume_l = out_ctxt->output->volume_l;
5553 out->volume_r = out_ctxt->output->volume_r;
5554 }
5555 }
5556 if (!out->a2dp_compress_mute) {
5557 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5558 }
5559 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005560 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305561 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005562 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305563 if (!out->a2dp_compress_mute)
5564 ret = out_set_compr_volume(stream, left, right);
5565 out->volume_l = left;
5566 out->volume_r = right;
5567 pthread_mutex_unlock(&out->compr_mute_lock);
5568 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005569 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005570 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005571 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5572 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5573 if (!out->standby) {
5574 audio_extn_utils_send_app_type_gain(out->dev,
5575 out->app_type_cfg.app_type,
5576 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005577 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005578 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005579 out->volume_l = left;
5580 out->volume_r = right;
5581 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005582 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5583 ALOGV("%s: MMAP set volume called", __func__);
5584 if (!out->standby)
5585 ret = out_set_mmap_volume(stream, left, right);
5586 out->volume_l = left;
5587 out->volume_r = right;
5588 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305589 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305590 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5591 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305592 /* Volume control for pcm playback */
5593 if (!out->standby)
5594 ret = out_set_pcm_volume(stream, left, right);
5595 else
5596 out->apply_volume = true;
5597
5598 out->volume_l = left;
5599 out->volume_r = right;
5600 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005601 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5602 ALOGV("%s: bus device set volume called", __func__);
5603 if (!out->standby)
5604 ret = out_set_pcm_volume(stream, left, right);
5605 out->volume_l = left;
5606 out->volume_r = right;
5607 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005608 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005610 return -ENOSYS;
5611}
5612
Zhou Songc9672822017-08-16 16:01:39 +08005613static void update_frames_written(struct stream_out *out, size_t bytes)
5614{
5615 size_t bpf = 0;
5616
5617 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5618 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5619 bpf = 1;
5620 else if (!is_offload_usecase(out->usecase))
5621 bpf = audio_bytes_per_sample(out->format) *
5622 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005623
5624 pthread_mutex_lock(&out->position_query_lock);
5625 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005626 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005627 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5628 }
5629 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005630}
5631
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005632int split_and_write_audio_haptic_data(struct stream_out *out,
5633 const void *buffer, size_t bytes_to_write)
5634{
5635 struct audio_device *adev = out->dev;
5636
5637 int ret = 0;
5638 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5639 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5640 size_t frame_size = channel_count * bytes_per_sample;
5641 size_t frame_count = bytes_to_write / frame_size;
5642
5643 bool force_haptic_path =
5644 property_get_bool("vendor.audio.test_haptic", false);
5645
5646 // extract Haptics data from Audio buffer
5647 bool alloc_haptic_buffer = false;
5648 int haptic_channel_count = adev->haptics_config.channels;
5649 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5650 size_t audio_frame_size = frame_size - haptic_frame_size;
5651 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5652
5653 if (adev->haptic_buffer == NULL) {
5654 alloc_haptic_buffer = true;
5655 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5656 free(adev->haptic_buffer);
5657 adev->haptic_buffer_size = 0;
5658 alloc_haptic_buffer = true;
5659 }
5660
5661 if (alloc_haptic_buffer) {
5662 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005663 if(adev->haptic_buffer == NULL) {
5664 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5665 return -ENOMEM;
5666 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005667 adev->haptic_buffer_size = total_haptic_buffer_size;
5668 }
5669
5670 size_t src_index = 0, aud_index = 0, hap_index = 0;
5671 uint8_t *audio_buffer = (uint8_t *)buffer;
5672 uint8_t *haptic_buffer = adev->haptic_buffer;
5673
5674 // This is required for testing only. This works for stereo data only.
5675 // One channel is fed to audio stream and other to haptic stream for testing.
5676 if (force_haptic_path)
5677 audio_frame_size = haptic_frame_size = bytes_per_sample;
5678
5679 for (size_t i = 0; i < frame_count; i++) {
5680 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5681 audio_frame_size);
5682 aud_index += audio_frame_size;
5683 src_index += audio_frame_size;
5684
5685 if (adev->haptic_pcm)
5686 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5687 haptic_frame_size);
5688 hap_index += haptic_frame_size;
5689 src_index += haptic_frame_size;
5690
5691 // This is required for testing only.
5692 // Discard haptic channel data.
5693 if (force_haptic_path)
5694 src_index += haptic_frame_size;
5695 }
5696
5697 // write to audio pipeline
5698 ret = pcm_write(out->pcm, (void *)audio_buffer,
5699 frame_count * audio_frame_size);
5700
5701 // write to haptics pipeline
5702 if (adev->haptic_pcm)
5703 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5704 frame_count * haptic_frame_size);
5705
5706 return ret;
5707}
5708
Aalique Grahame22e49102018-12-18 14:23:57 -08005709#ifdef NO_AUDIO_OUT
5710static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5711 const void *buffer __unused, size_t bytes)
5712{
5713 struct stream_out *out = (struct stream_out *)stream;
5714
5715 /* No Output device supported other than BT for playback.
5716 * Sleep for the amount of buffer duration
5717 */
5718 lock_output_stream(out);
5719 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5720 (const struct audio_stream_out *)&out->stream) /
5721 out_get_sample_rate(&out->stream.common));
5722 pthread_mutex_unlock(&out->lock);
5723 return bytes;
5724}
5725#endif
5726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005727static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5728 size_t bytes)
5729{
5730 struct stream_out *out = (struct stream_out *)stream;
5731 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005732 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305733 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005734 const size_t frame_size = audio_stream_out_frame_size(stream);
5735 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305736 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005737 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005738
Haynes Mathew George380745d2017-10-04 15:27:45 -07005739 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005740 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305741
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305742 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005743
Dhananjay Kumarac341582017-02-23 23:42:25 +05305744 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305745 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305746 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5747 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005748 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305749 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305750 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305751 ALOGD(" %s: sound card is not active/SSR state", __func__);
5752 ret= -EIO;
5753 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305754 }
5755 }
5756
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305757 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305758 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305759 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305760 goto exit;
5761 }
5762
Haynes Mathew George16081042017-05-31 17:16:49 -07005763 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5764 ret = -EINVAL;
5765 goto exit;
5766 }
5767
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005768 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305769 !out->is_iec61937_info_available) {
5770
5771 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5772 out->is_iec61937_info_available = true;
5773 } else if (audio_extn_passthru_is_enabled()) {
5774 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305775 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305776
5777 if((out->format == AUDIO_FORMAT_DTS) ||
5778 (out->format == AUDIO_FORMAT_DTS_HD)) {
5779 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5780 buffer, bytes);
5781 if (ret) {
5782 if (ret != -ENOSYS) {
5783 out->is_iec61937_info_available = false;
5784 ALOGD("iec61937 transmission info not yet updated retry");
5785 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305786 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305787 /* if stream has started and after that there is
5788 * stream config change (iec transmission config)
5789 * then trigger select_device to update backend configuration.
5790 */
5791 out->stream_config_changed = true;
5792 pthread_mutex_lock(&adev->lock);
5793 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305794 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005795 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305796 ret = -EINVAL;
5797 goto exit;
5798 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305799 pthread_mutex_unlock(&adev->lock);
5800 out->stream_config_changed = false;
5801 out->is_iec61937_info_available = true;
5802 }
5803 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305804
Meng Wang4c32fb42020-01-16 17:57:11 +08005805#ifdef AUDIO_GKI_ENABLED
5806 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5807 compr_passthr = out->compr_config.codec->reserved[0];
5808#else
5809 compr_passthr = out->compr_config.codec->compr_passthr;
5810#endif
5811
Garmond Leung317cbf12017-09-13 16:20:50 -07005812 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005813 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305814 (out->is_iec61937_info_available == true)) {
5815 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5816 ret = -EINVAL;
5817 goto exit;
5818 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305819 }
5820 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305821
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005822 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005823 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005824 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5825 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305826 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305827 ret = -EIO;
5828 goto exit;
5829 }
5830 }
5831 }
5832
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005833 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005834 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005835 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5836
Eric Laurent150dbfe2013-02-27 14:31:02 -08005837 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005838 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5839 ret = voice_extn_compress_voip_start_output_stream(out);
5840 else
5841 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005842 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005843 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005844 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005845 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005846 goto exit;
5847 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305848 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005849 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
vivek mehtab72d08d2016-04-29 03:16:47 -07005850 if (last_known_cal_step != -1) {
5851 ALOGD("%s: retry previous failed cal level set", __func__);
5852 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305853 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005854 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305855
5856 if ((out->is_iec61937_info_available == true) &&
5857 (audio_extn_passthru_is_passthrough_stream(out))&&
5858 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5859 ret = -EINVAL;
5860 goto exit;
5861 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305862 if (out->set_dual_mono)
5863 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005864
5865 // log startup time in ms.
5866 simple_stats_log(
5867 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005868 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005869
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005870 if (adev->is_channel_status_set == false &&
5871 compare_device_type(&out->device_list,
5872 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005873 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305874 adev->is_channel_status_set = true;
5875 }
5876
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305877 if ((adev->use_old_pspd_mix_ctrl == true) &&
5878 (out->pspd_coeff_sent == false)) {
5879 /*
5880 * Need to resend pspd coefficients after stream started for
5881 * older kernel version as it does not save the coefficients
5882 * and also stream has to be started for coeff to apply.
5883 */
5884 usecase = get_usecase_from_list(adev, out->usecase);
5885 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305886 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305887 out->pspd_coeff_sent = true;
5888 }
5889 }
5890
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005891 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005892 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005893 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005894 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005895 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5896 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305897 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5898 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005899 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305900 out->send_next_track_params = false;
5901 out->is_compr_metadata_avail = false;
5902 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005903 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305904 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305905 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005906
Ashish Jain83a6cc22016-06-28 14:34:17 +05305907 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305908 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305909 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305910 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005911 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305912 return -EINVAL;
5913 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305914 audio_format_t dst_format = out->hal_op_format;
5915 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305916
Dieter Luecking5d57def2018-09-07 14:23:37 +02005917 /* prevent division-by-zero */
5918 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5919 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5920 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5921 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305922 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005923 ATRACE_END();
5924 return -EINVAL;
5925 }
5926
Ashish Jainf1eaa582016-05-23 20:54:24 +05305927 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5928 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5929
Ashish Jain83a6cc22016-06-28 14:34:17 +05305930 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305931 dst_format,
5932 buffer,
5933 src_format,
5934 frames);
5935
Ashish Jain83a6cc22016-06-28 14:34:17 +05305936 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305937 bytes_to_write);
5938
5939 /*Convert written bytes in audio flinger format*/
5940 if (ret > 0)
5941 ret = ((ret * format_to_bitwidth_table[out->format]) /
5942 format_to_bitwidth_table[dst_format]);
5943 }
5944 } else
5945 ret = compress_write(out->compr, buffer, bytes);
5946
Zhou Songc9672822017-08-16 16:01:39 +08005947 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5948 update_frames_written(out, bytes);
5949
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305950 if (ret < 0)
5951 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005952 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305953 /*msg to cb thread only if non blocking write is enabled*/
5954 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305955 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005956 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305957 } else if (-ENETRESET == ret) {
5958 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305959 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305960 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305961 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005962 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305963 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005964 }
Ashish Jain5106d362016-05-11 19:23:33 +05305965
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305966 /* Call compr start only when non-zero bytes of data is there to be rendered */
5967 if (!out->playback_started && ret > 0) {
5968 int status = compress_start(out->compr);
5969 if (status < 0) {
5970 ret = status;
5971 ALOGE("%s: compr start failed with err %d", __func__, errno);
5972 goto exit;
5973 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005974 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005975 out->playback_started = 1;
5976 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005977
5978 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5979 popcount(out->channel_mask),
5980 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005981 }
5982 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005983 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005984 return ret;
5985 } else {
5986 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005987 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005988 if (out->muted)
5989 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005990 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5991 __func__, frames, frame_size, bytes_to_write);
5992
Aalique Grahame22e49102018-12-18 14:23:57 -08005993 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005994 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5995 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5996 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005997 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5998 int16_t *src = (int16_t *)buffer;
5999 int16_t *dst = (int16_t *)buffer;
6000
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006001 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006002 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006003 "out_write called for %s use case with wrong properties",
6004 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006005
6006 /*
6007 * FIXME: this can be removed once audio flinger mixer supports
6008 * mono output
6009 */
6010
6011 /*
6012 * Code below goes over each frame in the buffer and adds both
6013 * L and R samples and then divides by 2 to convert to mono
6014 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006015 if (channel_count == 2) {
6016 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6017 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6018 }
6019 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006020 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006021 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006022
6023 // Note: since out_get_presentation_position() is called alternating with out_write()
6024 // by AudioFlinger, we can check underruns using the prior timestamp read.
6025 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6026 if (out->last_fifo_valid) {
6027 // compute drain to see if there is an underrun.
6028 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
Dhananjay Kumara4429632020-07-11 02:53:37 +05306029 int64_t time_diff_ns = current_ns - out->last_fifo_time_ns;
6030 int64_t frames_by_time =
6031 ((time_diff_ns > 0) && (time_diff_ns < (INT64_MAX / out->config.rate))) ?
6032 (time_diff_ns * out->config.rate / NANOS_PER_SECOND) : 0;
Andy Hunga1f48fa2019-07-01 18:14:53 -07006033 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6034
6035 if (underrun > 0) {
6036 simple_stats_log(&out->fifo_underruns, underrun);
6037
6038 ALOGW("%s: underrun(%lld) "
6039 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6040 __func__,
6041 (long long)out->fifo_underruns.n,
6042 (long long)frames_by_time,
6043 (long long)out->last_fifo_frames_remaining);
6044 }
6045 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6046 }
6047
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306048 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006049
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006050 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006051
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006052 if (out->config.rate)
6053 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6054 out->config.rate;
6055
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006056 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006057 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6058
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006059 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006060 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006061 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306062 out->convert_buffer != NULL) {
6063
6064 memcpy_by_audio_format(out->convert_buffer,
6065 out->hal_op_format,
6066 buffer,
6067 out->hal_ip_format,
6068 out->config.period_size * out->config.channels);
6069
6070 ret = pcm_write(out->pcm, out->convert_buffer,
6071 (out->config.period_size *
6072 out->config.channels *
6073 format_to_bitwidth_table[out->hal_op_format]));
6074 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306075 /*
6076 * To avoid underrun in DSP when the application is not pumping
6077 * data at required rate, check for the no. of bytes and ignore
6078 * pcm_write if it is less than actual buffer size.
6079 * It is a work around to a change in compress VOIP driver.
6080 */
6081 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6082 bytes < (out->config.period_size * out->config.channels *
6083 audio_bytes_per_sample(out->format))) {
6084 size_t voip_buf_size =
6085 out->config.period_size * out->config.channels *
6086 audio_bytes_per_sample(out->format);
6087 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6088 __func__, bytes, voip_buf_size);
6089 usleep(((uint64_t)voip_buf_size - bytes) *
6090 1000000 / audio_stream_out_frame_size(stream) /
6091 out_get_sample_rate(&out->stream.common));
6092 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006093 } else {
6094 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6095 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6096 else
6097 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6098 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306099 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006100
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006101 release_out_focus(out);
6102
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306103 if (ret < 0)
6104 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006105 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306106 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006107 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006108 }
6109
6110exit:
Zhou Songc9672822017-08-16 16:01:39 +08006111 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306112 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306113 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306114 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006115 pthread_mutex_unlock(&out->lock);
6116
6117 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006118 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006119 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306120 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306121 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306122 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306123 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306124 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306125 out->standby = true;
6126 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306127 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006128 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6129 /* prevent division-by-zero */
6130 uint32_t stream_size = audio_stream_out_frame_size(stream);
6131 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006132
Dieter Luecking5d57def2018-09-07 14:23:37 +02006133 if ((stream_size == 0) || (srate == 0)) {
6134 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6135 ATRACE_END();
6136 return -EINVAL;
6137 }
6138 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6139 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006140 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306141 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006142 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006143 return ret;
6144 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006145 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006146 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006147 return bytes;
6148}
6149
6150static int out_get_render_position(const struct audio_stream_out *stream,
6151 uint32_t *dsp_frames)
6152{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006153 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006154
6155 if (dsp_frames == NULL)
6156 return -EINVAL;
6157
6158 *dsp_frames = 0;
6159 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006160 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306161
6162 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6163 * this operation and adev_close_output_stream(where out gets reset).
6164 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306165 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006166 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306167 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006168 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306169 return 0;
6170 }
6171
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006172 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306173 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306174 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006175 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306176 if (ret < 0)
6177 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006178 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306179 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006180 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306181 if (-ENETRESET == ret) {
6182 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306183 out->card_status = CARD_STATUS_OFFLINE;
6184 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306185 } else if(ret < 0) {
6186 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306187 ret = -EINVAL;
6188 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306189 /*
6190 * Handle corner case where compress session is closed during SSR
6191 * and timestamp is queried
6192 */
6193 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306194 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306195 } else if (out->prev_card_status_offline) {
6196 ALOGE("ERROR: previously sound card was offline,return error");
6197 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306198 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306199 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006200 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306201 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306202 pthread_mutex_unlock(&out->lock);
6203 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006204 } else if (audio_is_linear_pcm(out->format)) {
6205 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006206 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006207 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006208 } else
6209 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006210}
6211
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006212static int out_add_audio_effect(const struct audio_stream *stream __unused,
6213 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006214{
6215 return 0;
6216}
6217
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006218static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6219 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006220{
6221 return 0;
6222}
6223
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006224static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6225 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006226{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306227 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006228}
6229
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006230static int out_get_presentation_position(const struct audio_stream_out *stream,
6231 uint64_t *frames, struct timespec *timestamp)
6232{
6233 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306234 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006235 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006236
Ashish Jain5106d362016-05-11 19:23:33 +05306237 /* below piece of code is not guarded against any lock because audioFliner serializes
6238 * this operation and adev_close_output_stream( where out gets reset).
6239 */
6240 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306241 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006242 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306243 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6244 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6245 return 0;
6246 }
6247
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006248 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006249
Ashish Jain5106d362016-05-11 19:23:33 +05306250 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6251 ret = compress_get_tstamp(out->compr, &dsp_frames,
6252 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006253 // Adjustment accounts for A2dp encoder latency with offload usecases
6254 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006255 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006256 unsigned long offset =
6257 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6258 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6259 }
Ashish Jain5106d362016-05-11 19:23:33 +05306260 ALOGVV("%s rendered frames %ld sample_rate %d",
6261 __func__, dsp_frames, out->sample_rate);
6262 *frames = dsp_frames;
6263 if (ret < 0)
6264 ret = -errno;
6265 if (-ENETRESET == ret) {
6266 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306267 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306268 ret = -EINVAL;
6269 } else
6270 ret = 0;
6271 /* this is the best we can do */
6272 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006273 } else {
6274 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006275 unsigned int avail;
6276 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006277 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006278 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006279
Andy Hunga1f48fa2019-07-01 18:14:53 -07006280 if (out->kernel_buffer_size > avail) {
6281 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6282 } else {
6283 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6284 __func__, avail, out->kernel_buffer_size);
6285 avail = out->kernel_buffer_size;
6286 frames_temp = out->last_fifo_frames_remaining = 0;
6287 }
6288 out->last_fifo_valid = true;
6289 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6290
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006291 if (out->written >= frames_temp)
6292 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006293
Andy Hunga1f48fa2019-07-01 18:14:53 -07006294 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6295 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6296
Weiyin Jiangd4633762018-03-16 12:05:03 +08006297 // This adjustment accounts for buffering after app processor.
6298 // It is based on estimated DSP latency per use case, rather than exact.
Robert Lee58215542019-07-15 20:55:12 +08006299 pthread_mutex_lock(&adev->lock);
6300 frames_temp = platform_render_latency(out->dev, out->usecase) *
6301 out->sample_rate / 1000000LL;
6302 pthread_mutex_unlock(&adev->lock);
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006303 if (signed_frames >= frames_temp)
6304 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006305
Weiyin Jiangd4633762018-03-16 12:05:03 +08006306 // Adjustment accounts for A2dp encoder latency with non offload usecases
6307 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006308 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006309 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6310 if (signed_frames >= frames_temp)
6311 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006312 }
6313
6314 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006315 *frames = signed_frames;
6316 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006317 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006318 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6319 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006320 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306321 *frames = out->written;
6322 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306323 if (is_offload_usecase(out->usecase))
6324 ret = -EINVAL;
6325 else
6326 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006327 }
6328 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006329 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006330 return ret;
6331}
6332
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006333static int out_set_callback(struct audio_stream_out *stream,
6334 stream_callback_t callback, void *cookie)
6335{
6336 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006337 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006338
6339 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006340 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006341 out->client_callback = callback;
6342 out->client_cookie = cookie;
6343 if (out->adsp_hdlr_stream_handle) {
6344 ret = audio_extn_adsp_hdlr_stream_set_callback(
6345 out->adsp_hdlr_stream_handle,
6346 callback,
6347 cookie);
6348 if (ret)
6349 ALOGW("%s:adsp hdlr callback registration failed %d",
6350 __func__, ret);
6351 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006352 pthread_mutex_unlock(&out->lock);
6353 return 0;
6354}
6355
6356static int out_pause(struct audio_stream_out* stream)
6357{
6358 struct stream_out *out = (struct stream_out *)stream;
6359 int status = -ENOSYS;
6360 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006361 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006362 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306363 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006364 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006365 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306366 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306367 status = compress_pause(out->compr);
6368
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006369 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006370
Mingming Yin21854652016-04-13 11:54:02 -07006371 if (audio_extn_passthru_is_active()) {
6372 ALOGV("offload use case, pause passthru");
6373 audio_extn_passthru_on_pause(out);
6374 }
6375
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306376 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006377 audio_extn_dts_notify_playback_state(out->usecase, 0,
6378 out->sample_rate, popcount(out->channel_mask),
6379 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006380 }
6381 pthread_mutex_unlock(&out->lock);
6382 }
6383 return status;
6384}
6385
6386static int out_resume(struct audio_stream_out* stream)
6387{
6388 struct stream_out *out = (struct stream_out *)stream;
6389 int status = -ENOSYS;
6390 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006391 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006392 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306393 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006394 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006395 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306396 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306397 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006398 }
6399 if (!status) {
6400 out->offload_state = OFFLOAD_STATE_PLAYING;
6401 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306402 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006403 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6404 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006405 }
6406 pthread_mutex_unlock(&out->lock);
6407 }
6408 return status;
6409}
6410
6411static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6412{
6413 struct stream_out *out = (struct stream_out *)stream;
6414 int status = -ENOSYS;
6415 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006416 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006417 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006418 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6419 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6420 else
6421 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6422 pthread_mutex_unlock(&out->lock);
6423 }
6424 return status;
6425}
6426
6427static int out_flush(struct audio_stream_out* stream)
6428{
6429 struct stream_out *out = (struct stream_out *)stream;
6430 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006431 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006432 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006433 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006434 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6435 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006436 } else {
6437 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6438 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006439 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006440 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006441 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006442 return 0;
6443 }
6444 return -ENOSYS;
6445}
6446
Haynes Mathew George16081042017-05-31 17:16:49 -07006447static int out_stop(const struct audio_stream_out* stream)
6448{
6449 struct stream_out *out = (struct stream_out *)stream;
6450 struct audio_device *adev = out->dev;
6451 int ret = -ENOSYS;
6452
6453 ALOGV("%s", __func__);
6454 pthread_mutex_lock(&adev->lock);
6455 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6456 out->playback_started && out->pcm != NULL) {
6457 pcm_stop(out->pcm);
6458 ret = stop_output_stream(out);
6459 out->playback_started = false;
6460 }
6461 pthread_mutex_unlock(&adev->lock);
6462 return ret;
6463}
6464
6465static int out_start(const struct audio_stream_out* stream)
6466{
6467 struct stream_out *out = (struct stream_out *)stream;
6468 struct audio_device *adev = out->dev;
6469 int ret = -ENOSYS;
6470
6471 ALOGV("%s", __func__);
6472 pthread_mutex_lock(&adev->lock);
6473 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6474 !out->playback_started && out->pcm != NULL) {
6475 ret = start_output_stream(out);
6476 if (ret == 0) {
6477 out->playback_started = true;
6478 }
6479 }
6480 pthread_mutex_unlock(&adev->lock);
6481 return ret;
6482}
6483
6484/*
6485 * Modify config->period_count based on min_size_frames
6486 */
6487static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6488{
6489 int periodCountRequested = (min_size_frames + config->period_size - 1)
6490 / config->period_size;
6491 int periodCount = MMAP_PERIOD_COUNT_MIN;
6492
6493 ALOGV("%s original config.period_size = %d config.period_count = %d",
6494 __func__, config->period_size, config->period_count);
6495
6496 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6497 periodCount *= 2;
6498 }
6499 config->period_count = periodCount;
6500
6501 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6502}
6503
Phil Burkfe17efd2019-03-25 10:23:35 -07006504// Read offset for the positional timestamp from a persistent vendor property.
6505// This is to workaround apparent inaccuracies in the timing information that
6506// is used by the AAudio timing model. The inaccuracies can cause glitches.
6507static int64_t get_mmap_out_time_offset() {
6508 const int32_t kDefaultOffsetMicros = 0;
6509 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006510 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006511 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6512 return mmap_time_offset_micros * (int64_t)1000;
6513}
6514
Haynes Mathew George16081042017-05-31 17:16:49 -07006515static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6516 int32_t min_size_frames,
6517 struct audio_mmap_buffer_info *info)
6518{
6519 struct stream_out *out = (struct stream_out *)stream;
6520 struct audio_device *adev = out->dev;
6521 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006522 unsigned int offset1 = 0;
6523 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006524 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006525 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006526 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006527
Arun Mirpuri5d170872019-03-26 13:21:31 -07006528 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306529 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006530 pthread_mutex_lock(&adev->lock);
6531
Sharad Sanglec6f32552018-05-04 16:15:38 +05306532 if (CARD_STATUS_OFFLINE == out->card_status ||
6533 CARD_STATUS_OFFLINE == adev->card_status) {
6534 ALOGW("out->card_status or adev->card_status offline, try again");
6535 ret = -EIO;
6536 goto exit;
6537 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306538 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006539 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6540 ret = -EINVAL;
6541 goto exit;
6542 }
6543 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6544 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6545 ret = -ENOSYS;
6546 goto exit;
6547 }
6548 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6549 if (out->pcm_device_id < 0) {
6550 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6551 __func__, out->pcm_device_id, out->usecase);
6552 ret = -EINVAL;
6553 goto exit;
6554 }
6555
6556 adjust_mmap_period_count(&out->config, min_size_frames);
6557
Arun Mirpuri5d170872019-03-26 13:21:31 -07006558 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006559 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6560 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6561 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306562 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306563 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6564 out->card_status = CARD_STATUS_OFFLINE;
6565 adev->card_status = CARD_STATUS_OFFLINE;
6566 ret = -EIO;
6567 goto exit;
6568 }
6569
Haynes Mathew George16081042017-05-31 17:16:49 -07006570 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6571 step = "open";
6572 ret = -ENODEV;
6573 goto exit;
6574 }
6575 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6576 if (ret < 0) {
6577 step = "begin";
6578 goto exit;
6579 }
juyuchen626833d2019-06-04 16:48:02 +08006580
6581 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006582 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006583 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006584 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006585 ret = platform_get_mmap_data_fd(adev->platform,
6586 out->pcm_device_id, 0 /*playback*/,
6587 &info->shared_memory_fd,
6588 &mmap_size);
6589 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006590 // Fall back to non exclusive mode
6591 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6592 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006593 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6594 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6595
Arun Mirpuri5d170872019-03-26 13:21:31 -07006596 if (mmap_size < buffer_size) {
6597 step = "mmap";
6598 goto exit;
6599 }
juyuchen626833d2019-06-04 16:48:02 +08006600 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006601 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006602 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006603 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006604
6605 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6606 if (ret < 0) {
6607 step = "commit";
6608 goto exit;
6609 }
6610
Phil Burkfe17efd2019-03-25 10:23:35 -07006611 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6612
Haynes Mathew George16081042017-05-31 17:16:49 -07006613 out->standby = false;
6614 ret = 0;
6615
Arun Mirpuri5d170872019-03-26 13:21:31 -07006616 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006617 __func__, info->shared_memory_address, info->buffer_size_frames);
6618
6619exit:
6620 if (ret != 0) {
6621 if (out->pcm == NULL) {
6622 ALOGE("%s: %s - %d", __func__, step, ret);
6623 } else {
6624 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6625 pcm_close(out->pcm);
6626 out->pcm = NULL;
6627 }
6628 }
6629 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306630 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006631 return ret;
6632}
6633
6634static int out_get_mmap_position(const struct audio_stream_out *stream,
6635 struct audio_mmap_position *position)
6636{
6637 struct stream_out *out = (struct stream_out *)stream;
6638 ALOGVV("%s", __func__);
6639 if (position == NULL) {
6640 return -EINVAL;
6641 }
6642 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006643 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006644 return -ENOSYS;
6645 }
6646 if (out->pcm == NULL) {
6647 return -ENOSYS;
6648 }
6649
6650 struct timespec ts = { 0, 0 };
6651 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6652 if (ret < 0) {
6653 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6654 return ret;
6655 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006656 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6657 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006658 return 0;
6659}
6660
6661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006662/** audio_stream_in implementation **/
6663static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6664{
6665 struct stream_in *in = (struct stream_in *)stream;
6666
6667 return in->config.rate;
6668}
6669
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006670static int in_set_sample_rate(struct audio_stream *stream __unused,
6671 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006672{
6673 return -ENOSYS;
6674}
6675
6676static size_t in_get_buffer_size(const struct audio_stream *stream)
6677{
6678 struct stream_in *in = (struct stream_in *)stream;
6679
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006680 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6681 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006682 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6683 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306684 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306685 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006686
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006687 return in->config.period_size * in->af_period_multiplier *
6688 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006689}
6690
6691static uint32_t in_get_channels(const struct audio_stream *stream)
6692{
6693 struct stream_in *in = (struct stream_in *)stream;
6694
6695 return in->channel_mask;
6696}
6697
6698static audio_format_t in_get_format(const struct audio_stream *stream)
6699{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006700 struct stream_in *in = (struct stream_in *)stream;
6701
6702 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006703}
6704
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006705static int in_set_format(struct audio_stream *stream __unused,
6706 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006707{
6708 return -ENOSYS;
6709}
6710
6711static int in_standby(struct audio_stream *stream)
6712{
6713 struct stream_in *in = (struct stream_in *)stream;
6714 struct audio_device *adev = in->dev;
6715 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306716 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6717 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006718 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306719
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006720 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006721 if (!in->standby && in->is_st_session) {
6722 ALOGD("%s: sound trigger pcm stop lab", __func__);
6723 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006724 if (adev->num_va_sessions > 0)
6725 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006726 in->standby = 1;
6727 }
6728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006729 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006730 if (adev->adm_deregister_stream)
6731 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6732
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006733 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006734 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006735 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006736 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006737 voice_extn_compress_voip_close_input_stream(stream);
6738 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006739 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6740 do_stop = in->capture_started;
6741 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006742 if (in->mmap_shared_memory_fd >= 0) {
6743 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6744 __func__, in->mmap_shared_memory_fd);
6745 close(in->mmap_shared_memory_fd);
6746 in->mmap_shared_memory_fd = -1;
6747 }
Zhou Songa8895042016-07-05 17:54:22 +08006748 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306749 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306750 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006751 }
6752
Arun Mirpuri5d170872019-03-26 13:21:31 -07006753 if (in->pcm) {
6754 ATRACE_BEGIN("pcm_in_close");
6755 pcm_close(in->pcm);
6756 ATRACE_END();
6757 in->pcm = NULL;
6758 }
6759
Carter Hsu2e429db2019-05-14 18:50:52 +08006760 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006761 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006762
George Gao3018ede2019-10-23 13:23:00 -07006763 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6764 if (adev->num_va_sessions > 0)
6765 adev->num_va_sessions--;
6766 }
Quinn Malef6050362019-01-30 15:55:40 -08006767
Eric Laurent150dbfe2013-02-27 14:31:02 -08006768 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006769 }
6770 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006771 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006772 return status;
6773}
6774
Aalique Grahame22e49102018-12-18 14:23:57 -08006775static int in_dump(const struct audio_stream *stream,
6776 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006777{
Aalique Grahame22e49102018-12-18 14:23:57 -08006778 struct stream_in *in = (struct stream_in *)stream;
6779
6780 // We try to get the lock for consistency,
6781 // but it isn't necessary for these variables.
6782 // If we're not in standby, we may be blocked on a read.
6783 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6784 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6785 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6786 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6787
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006788 char buffer[256]; // for statistics formatting
6789 if (in->start_latency_ms.n > 0) {
6790 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6791 dprintf(fd, " Start latency ms: %s\n", buffer);
6792 }
6793
Aalique Grahame22e49102018-12-18 14:23:57 -08006794 if (locked) {
6795 pthread_mutex_unlock(&in->lock);
6796 }
6797
6798 // dump error info
6799 (void)error_log_dump(
6800 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006802 return 0;
6803}
6804
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306805static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6806{
6807 if (!stream || !parms)
6808 return;
6809
6810 struct stream_in *in = (struct stream_in *)stream;
6811 struct audio_device *adev = in->dev;
6812
6813 card_status_t status;
6814 int card;
6815 if (parse_snd_card_status(parms, &card, &status) < 0)
6816 return;
6817
6818 pthread_mutex_lock(&adev->lock);
6819 bool valid_cb = (card == adev->snd_card);
6820 pthread_mutex_unlock(&adev->lock);
6821
6822 if (!valid_cb)
6823 return;
6824
6825 lock_input_stream(in);
6826 if (in->card_status != status)
6827 in->card_status = status;
6828 pthread_mutex_unlock(&in->lock);
6829
6830 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6831 use_case_table[in->usecase],
6832 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6833
6834 // a better solution would be to report error back to AF and let
6835 // it put the stream to standby
6836 if (status == CARD_STATUS_OFFLINE)
6837 in_standby(&in->stream.common);
6838
6839 return;
6840}
6841
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006842int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006843 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006844 audio_source_t source)
6845{
6846 struct audio_device *adev = in->dev;
6847 int ret = 0;
6848
6849 lock_input_stream(in);
6850 pthread_mutex_lock(&adev->lock);
6851
6852 /* no audio source uses val == 0 */
6853 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6854 in->source = source;
6855 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6856 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6857 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6858 (in->config.rate == 8000 || in->config.rate == 16000 ||
6859 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6860 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6861 ret = voice_extn_compress_voip_open_input_stream(in);
6862 if (ret != 0) {
6863 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6864 __func__, ret);
6865 }
6866 }
6867 }
6868
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006869 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6870 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006871 // Workaround: If routing to an non existing usb device, fail gracefully
6872 // The routing request will otherwise block during 10 second
6873 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006874 struct str_parms *usb_addr =
6875 str_parms_create_str(get_usb_device_address(devices));
6876 if (is_usb_in_device_type(devices) && usb_addr &&
6877 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006878 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6879 ret = -ENOSYS;
6880 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006881 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006882 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006883 if (!in->standby && !in->is_st_session) {
6884 ALOGV("update input routing change");
6885 // inform adm before actual routing to prevent glitches.
6886 if (adev->adm_on_routing_change) {
6887 adev->adm_on_routing_change(adev->adm_data,
6888 in->capture_handle);
6889 ret = select_devices(adev, in->usecase);
6890 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6891 adev->adm_routing_changed = true;
6892 }
6893 }
6894 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006895 if (usb_addr)
6896 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006897 }
6898 pthread_mutex_unlock(&adev->lock);
6899 pthread_mutex_unlock(&in->lock);
6900
6901 ALOGD("%s: exit: status(%d)", __func__, ret);
6902 return ret;
6903}
6904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006905static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6906{
6907 struct stream_in *in = (struct stream_in *)stream;
6908 struct audio_device *adev = in->dev;
6909 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006910 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306911 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006912
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306913 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006914 parms = str_parms_create_str(kvpairs);
6915
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306916 if (!parms)
6917 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006918 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006919 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006920
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306921 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6922 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306923 strlcpy(in->profile, value, sizeof(in->profile));
6924 ALOGV("updating stream profile with value '%s'", in->profile);
6925 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6926 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006927 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306928 in->sample_rate, in->bit_width,
6929 in->profile, &in->app_type_cfg);
6930 }
6931
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006932 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006933 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006934
6935 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306936error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306937 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006938}
6939
6940static char* in_get_parameters(const struct audio_stream *stream,
6941 const char *keys)
6942{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006943 struct stream_in *in = (struct stream_in *)stream;
6944 struct str_parms *query = str_parms_create_str(keys);
6945 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006946 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006947
6948 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006949 if (reply) {
6950 str_parms_destroy(reply);
6951 }
6952 if (query) {
6953 str_parms_destroy(query);
6954 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006955 ALOGE("in_get_parameters: failed to create query or reply");
6956 return NULL;
6957 }
6958
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006959 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006960
6961 voice_extn_in_get_parameters(in, query, reply);
6962
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006963 stream_get_parameter_channels(query, reply,
6964 &in->supported_channel_masks[0]);
6965 stream_get_parameter_formats(query, reply,
6966 &in->supported_formats[0]);
6967 stream_get_parameter_rates(query, reply,
6968 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006969 str = str_parms_to_str(reply);
6970 str_parms_destroy(query);
6971 str_parms_destroy(reply);
6972
6973 ALOGV("%s: exit: returns - %s", __func__, str);
6974 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006975}
6976
Aalique Grahame22e49102018-12-18 14:23:57 -08006977static int in_set_gain(struct audio_stream_in *stream,
6978 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006979{
Aalique Grahame22e49102018-12-18 14:23:57 -08006980 struct stream_in *in = (struct stream_in *)stream;
6981 char mixer_ctl_name[128];
6982 struct mixer_ctl *ctl;
6983 int ctl_value;
6984
6985 ALOGV("%s: gain %f", __func__, gain);
6986
6987 if (stream == NULL)
6988 return -EINVAL;
6989
6990 /* in_set_gain() only used to silence MMAP capture for now */
6991 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6992 return -ENOSYS;
6993
6994 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6995
6996 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6997 if (!ctl) {
6998 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6999 __func__, mixer_ctl_name);
7000 return -ENOSYS;
7001 }
7002
7003 if (gain < RECORD_GAIN_MIN)
7004 gain = RECORD_GAIN_MIN;
7005 else if (gain > RECORD_GAIN_MAX)
7006 gain = RECORD_GAIN_MAX;
7007 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7008
7009 mixer_ctl_set_value(ctl, 0, ctl_value);
7010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007011 return 0;
7012}
7013
7014static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7015 size_t bytes)
7016{
7017 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307018
7019 if (in == NULL) {
7020 ALOGE("%s: stream_in ptr is NULL", __func__);
7021 return -EINVAL;
7022 }
7023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007024 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307025 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307026 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007027
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007028 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307029
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007030 if (in->is_st_session) {
7031 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7032 /* Read from sound trigger HAL */
7033 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007034 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007035 if (adev->num_va_sessions < UINT_MAX)
7036 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007037 in->standby = 0;
7038 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007039 pthread_mutex_unlock(&in->lock);
7040 return bytes;
7041 }
7042
Haynes Mathew George16081042017-05-31 17:16:49 -07007043 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7044 ret = -ENOSYS;
7045 goto exit;
7046 }
7047
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007048 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7049 !in->standby && adev->adm_routing_changed) {
7050 ret = -ENOSYS;
7051 goto exit;
7052 }
7053
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007054 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007055 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7056
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007057 pthread_mutex_lock(&adev->lock);
7058 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7059 ret = voice_extn_compress_voip_start_input_stream(in);
7060 else
7061 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007062 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7063 if (adev->num_va_sessions < UINT_MAX)
7064 adev->num_va_sessions++;
7065 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007066 pthread_mutex_unlock(&adev->lock);
7067 if (ret != 0) {
7068 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007069 }
7070 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007071
7072 // log startup time in ms.
7073 simple_stats_log(
7074 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007075 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007076
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307077 /* Avoid read if capture_stopped is set */
7078 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7079 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7080 ret = -EINVAL;
7081 goto exit;
7082 }
7083
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007084 // what's the duration requested by the client?
7085 long ns = 0;
7086
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307087 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007088 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7089 in->config.rate;
7090
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007091 ret = request_in_focus(in, ns);
7092 if (ret != 0)
7093 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007094 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007095
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307096 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307097 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7098 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307099 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007100 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307101 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007102 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007103 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007104 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007105 } else if (audio_extn_ffv_get_stream() == in) {
7106 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307107 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007108 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307109 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7110 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7111 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7112 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307113 ret = -EINVAL;
7114 goto exit;
7115 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307116 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307117 ret = -errno;
7118 }
7119 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307120 /* bytes read is always set to bytes for non compress usecases */
7121 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007122 }
7123
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007124 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007126 /*
Quinn Malef6050362019-01-30 15:55:40 -08007127 * Instead of writing zeroes here, we could trust the hardware to always
7128 * provide zeroes when muted. This is also muted with voice recognition
7129 * usecases so that other clients do not have access to voice recognition
7130 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007131 */
Quinn Malef6050362019-01-30 15:55:40 -08007132 if ((ret == 0 && voice_get_mic_mute(adev) &&
7133 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007134 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7135 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007136 (adev->num_va_sessions &&
7137 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7138 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7139 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007140 memset(buffer, 0, bytes);
7141
7142exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307143 frame_size = audio_stream_in_frame_size(stream);
7144 if (frame_size > 0)
7145 in->frames_read += bytes_read/frame_size;
7146
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007147 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307148 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007149 pthread_mutex_unlock(&in->lock);
7150
7151 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307152 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307153 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307154 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307155 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307156 in->standby = true;
7157 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307158 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307159 bytes_read = bytes;
7160 memset(buffer, 0, bytes);
7161 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007162 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007163 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7164 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007165 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307166 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307167 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007168 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307169 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007170}
7171
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007172static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007173{
7174 return 0;
7175}
7176
Aalique Grahame22e49102018-12-18 14:23:57 -08007177static int in_get_capture_position(const struct audio_stream_in *stream,
7178 int64_t *frames, int64_t *time)
7179{
7180 if (stream == NULL || frames == NULL || time == NULL) {
7181 return -EINVAL;
7182 }
7183 struct stream_in *in = (struct stream_in *)stream;
7184 int ret = -ENOSYS;
7185
7186 lock_input_stream(in);
7187 // note: ST sessions do not close the alsa pcm driver synchronously
7188 // on standby. Therefore, we may return an error even though the
7189 // pcm stream is still opened.
7190 if (in->standby) {
7191 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7192 "%s stream in standby but pcm not NULL for non ST session", __func__);
7193 goto exit;
7194 }
7195 if (in->pcm) {
7196 struct timespec timestamp;
7197 unsigned int avail;
7198 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7199 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007200 pthread_mutex_lock(&adev->lock);
7201 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
7202 - platform_capture_latency(in->dev, in->usecase) * 1000LL;
7203 pthread_mutex_unlock(&adev->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08007204 ret = 0;
7205 }
7206 }
7207exit:
7208 pthread_mutex_unlock(&in->lock);
7209 return ret;
7210}
7211
Carter Hsu2e429db2019-05-14 18:50:52 +08007212static int in_update_effect_list(bool add, effect_handle_t effect,
7213 struct listnode *head)
7214{
7215 struct listnode *node;
7216 struct in_effect_list *elist = NULL;
7217 struct in_effect_list *target = NULL;
7218 int ret = 0;
7219
7220 if (!head)
7221 return ret;
7222
7223 list_for_each(node, head) {
7224 elist = node_to_item(node, struct in_effect_list, list);
7225 if (elist->handle == effect) {
7226 target = elist;
7227 break;
7228 }
7229 }
7230
7231 if (add) {
7232 if (target) {
7233 ALOGD("effect %p already exist", effect);
7234 return ret;
7235 }
7236
7237 target = (struct in_effect_list *)
7238 calloc(1, sizeof(struct in_effect_list));
7239
7240 if (!target) {
7241 ALOGE("%s:fail to allocate memory", __func__);
7242 return -ENOMEM;
7243 }
7244
7245 target->handle = effect;
7246 list_add_tail(head, &target->list);
7247 } else {
7248 if (target) {
7249 list_remove(&target->list);
7250 free(target);
7251 }
7252 }
7253
7254 return ret;
7255}
7256
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007257static int add_remove_audio_effect(const struct audio_stream *stream,
7258 effect_handle_t effect,
7259 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007260{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007261 struct stream_in *in = (struct stream_in *)stream;
7262 int status = 0;
7263 effect_descriptor_t desc;
7264
7265 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007266 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7267
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007268 if (status != 0)
7269 return status;
7270
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007271 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007272 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007273 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007274 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7275 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007276 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007277
7278 in_update_effect_list(enable, effect, &in->aec_list);
7279 enable = !list_empty(&in->aec_list);
7280 if (enable == in->enable_aec)
7281 goto exit;
7282
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007283 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007284 ALOGD("AEC enable %d", enable);
7285
Aalique Grahame22e49102018-12-18 14:23:57 -08007286 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7287 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7288 in->dev->enable_voicerx = enable;
7289 struct audio_usecase *usecase;
7290 struct listnode *node;
7291 list_for_each(node, &in->dev->usecase_list) {
7292 usecase = node_to_item(node, struct audio_usecase, list);
7293 if (usecase->type == PCM_PLAYBACK)
7294 select_devices(in->dev, usecase->id);
7295 }
7296 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007297 if (!in->standby) {
7298 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7299 select_devices(in->dev, in->usecase);
7300 }
7301
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007302 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007303 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7304
7305 in_update_effect_list(enable, effect, &in->ns_list);
7306 enable = !list_empty(&in->ns_list);
7307 if (enable == in->enable_ns)
7308 goto exit;
7309
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007310 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007311 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007312 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007313 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7314 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007315 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7316 select_devices(in->dev, in->usecase);
7317 } else
7318 select_devices(in->dev, in->usecase);
7319 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007320 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007321exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007322 pthread_mutex_unlock(&in->dev->lock);
7323 pthread_mutex_unlock(&in->lock);
7324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007325 return 0;
7326}
7327
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007328static int in_add_audio_effect(const struct audio_stream *stream,
7329 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007330{
Eric Laurent994a6932013-07-17 11:51:42 -07007331 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007332 return add_remove_audio_effect(stream, effect, true);
7333}
7334
7335static int in_remove_audio_effect(const struct audio_stream *stream,
7336 effect_handle_t effect)
7337{
Eric Laurent994a6932013-07-17 11:51:42 -07007338 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007339 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007340}
7341
Derek Chenf939fb72018-11-13 13:34:41 -08007342streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7343 audio_io_handle_t input)
7344{
7345 struct listnode *node;
7346
7347 list_for_each(node, &dev->active_inputs_list) {
7348 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7349 streams_input_ctxt_t,
7350 list);
7351 if (in_ctxt->input->capture_handle == input) {
7352 return in_ctxt;
7353 }
7354 }
7355 return NULL;
7356}
7357
7358streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7359 audio_io_handle_t output)
7360{
7361 struct listnode *node;
7362
7363 list_for_each(node, &dev->active_outputs_list) {
7364 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7365 streams_output_ctxt_t,
7366 list);
7367 if (out_ctxt->output->handle == output) {
7368 return out_ctxt;
7369 }
7370 }
7371 return NULL;
7372}
7373
Haynes Mathew George16081042017-05-31 17:16:49 -07007374static int in_stop(const struct audio_stream_in* stream)
7375{
7376 struct stream_in *in = (struct stream_in *)stream;
7377 struct audio_device *adev = in->dev;
7378
7379 int ret = -ENOSYS;
7380 ALOGV("%s", __func__);
7381 pthread_mutex_lock(&adev->lock);
7382 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7383 in->capture_started && in->pcm != NULL) {
7384 pcm_stop(in->pcm);
7385 ret = stop_input_stream(in);
7386 in->capture_started = false;
7387 }
7388 pthread_mutex_unlock(&adev->lock);
7389 return ret;
7390}
7391
7392static int in_start(const struct audio_stream_in* stream)
7393{
7394 struct stream_in *in = (struct stream_in *)stream;
7395 struct audio_device *adev = in->dev;
7396 int ret = -ENOSYS;
7397
7398 ALOGV("%s in %p", __func__, in);
7399 pthread_mutex_lock(&adev->lock);
7400 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7401 !in->capture_started && in->pcm != NULL) {
7402 if (!in->capture_started) {
7403 ret = start_input_stream(in);
7404 if (ret == 0) {
7405 in->capture_started = true;
7406 }
7407 }
7408 }
7409 pthread_mutex_unlock(&adev->lock);
7410 return ret;
7411}
7412
Phil Burke0a86d12019-02-16 22:28:11 -08007413// Read offset for the positional timestamp from a persistent vendor property.
7414// This is to workaround apparent inaccuracies in the timing information that
7415// is used by the AAudio timing model. The inaccuracies can cause glitches.
7416static int64_t in_get_mmap_time_offset() {
7417 const int32_t kDefaultOffsetMicros = 0;
7418 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007419 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007420 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7421 return mmap_time_offset_micros * (int64_t)1000;
7422}
7423
Haynes Mathew George16081042017-05-31 17:16:49 -07007424static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7425 int32_t min_size_frames,
7426 struct audio_mmap_buffer_info *info)
7427{
7428 struct stream_in *in = (struct stream_in *)stream;
7429 struct audio_device *adev = in->dev;
7430 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007431 unsigned int offset1 = 0;
7432 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007433 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007434 uint32_t mmap_size = 0;
7435 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007436
7437 pthread_mutex_lock(&adev->lock);
7438 ALOGV("%s in %p", __func__, in);
7439
Sharad Sanglec6f32552018-05-04 16:15:38 +05307440 if (CARD_STATUS_OFFLINE == in->card_status||
7441 CARD_STATUS_OFFLINE == adev->card_status) {
7442 ALOGW("in->card_status or adev->card_status offline, try again");
7443 ret = -EIO;
7444 goto exit;
7445 }
7446
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307447 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007448 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7449 ret = -EINVAL;
7450 goto exit;
7451 }
7452 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7453 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7454 ALOGV("%s in %p", __func__, in);
7455 ret = -ENOSYS;
7456 goto exit;
7457 }
7458 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7459 if (in->pcm_device_id < 0) {
7460 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7461 __func__, in->pcm_device_id, in->usecase);
7462 ret = -EINVAL;
7463 goto exit;
7464 }
7465
7466 adjust_mmap_period_count(&in->config, min_size_frames);
7467
7468 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7469 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7470 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7471 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307472 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307473 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7474 in->card_status = CARD_STATUS_OFFLINE;
7475 adev->card_status = CARD_STATUS_OFFLINE;
7476 ret = -EIO;
7477 goto exit;
7478 }
7479
Haynes Mathew George16081042017-05-31 17:16:49 -07007480 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7481 step = "open";
7482 ret = -ENODEV;
7483 goto exit;
7484 }
7485
7486 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7487 if (ret < 0) {
7488 step = "begin";
7489 goto exit;
7490 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007491
juyuchen626833d2019-06-04 16:48:02 +08007492 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007493 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7494 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7495 info->burst_size_frames = in->config.period_size;
7496 ret = platform_get_mmap_data_fd(adev->platform,
7497 in->pcm_device_id, 1 /*capture*/,
7498 &info->shared_memory_fd,
7499 &mmap_size);
7500 if (ret < 0) {
7501 // Fall back to non exclusive mode
7502 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7503 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007504 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7505 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7506
Arun Mirpuri5d170872019-03-26 13:21:31 -07007507 if (mmap_size < buffer_size) {
7508 step = "mmap";
7509 goto exit;
7510 }
juyuchen626833d2019-06-04 16:48:02 +08007511 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007512 }
7513
7514 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007515
7516 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7517 if (ret < 0) {
7518 step = "commit";
7519 goto exit;
7520 }
7521
Phil Burke0a86d12019-02-16 22:28:11 -08007522 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7523
Haynes Mathew George16081042017-05-31 17:16:49 -07007524 in->standby = false;
7525 ret = 0;
7526
7527 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7528 __func__, info->shared_memory_address, info->buffer_size_frames);
7529
7530exit:
7531 if (ret != 0) {
7532 if (in->pcm == NULL) {
7533 ALOGE("%s: %s - %d", __func__, step, ret);
7534 } else {
7535 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7536 pcm_close(in->pcm);
7537 in->pcm = NULL;
7538 }
7539 }
7540 pthread_mutex_unlock(&adev->lock);
7541 return ret;
7542}
7543
7544static int in_get_mmap_position(const struct audio_stream_in *stream,
7545 struct audio_mmap_position *position)
7546{
7547 struct stream_in *in = (struct stream_in *)stream;
7548 ALOGVV("%s", __func__);
7549 if (position == NULL) {
7550 return -EINVAL;
7551 }
7552 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7553 return -ENOSYS;
7554 }
7555 if (in->pcm == NULL) {
7556 return -ENOSYS;
7557 }
7558 struct timespec ts = { 0, 0 };
7559 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7560 if (ret < 0) {
7561 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7562 return ret;
7563 }
Phil Burke0a86d12019-02-16 22:28:11 -08007564 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7565 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007566 return 0;
7567}
7568
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307569static int in_get_active_microphones(const struct audio_stream_in *stream,
7570 struct audio_microphone_characteristic_t *mic_array,
7571 size_t *mic_count) {
7572 struct stream_in *in = (struct stream_in *)stream;
7573 struct audio_device *adev = in->dev;
7574 ALOGVV("%s", __func__);
7575
7576 lock_input_stream(in);
7577 pthread_mutex_lock(&adev->lock);
7578 int ret = platform_get_active_microphones(adev->platform,
7579 audio_channel_count_from_in_mask(in->channel_mask),
7580 in->usecase, mic_array, mic_count);
7581 pthread_mutex_unlock(&adev->lock);
7582 pthread_mutex_unlock(&in->lock);
7583
7584 return ret;
7585}
7586
7587static int adev_get_microphones(const struct audio_hw_device *dev,
7588 struct audio_microphone_characteristic_t *mic_array,
7589 size_t *mic_count) {
7590 struct audio_device *adev = (struct audio_device *)dev;
7591 ALOGVV("%s", __func__);
7592
7593 pthread_mutex_lock(&adev->lock);
7594 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7595 pthread_mutex_unlock(&adev->lock);
7596
7597 return ret;
7598}
juyuchendb308c22019-01-21 11:57:17 -07007599
7600static void in_update_sink_metadata(struct audio_stream_in *stream,
7601 const struct sink_metadata *sink_metadata) {
7602
7603 if (stream == NULL
7604 || sink_metadata == NULL
7605 || sink_metadata->tracks == NULL) {
7606 return;
7607 }
7608
7609 int error = 0;
7610 struct stream_in *in = (struct stream_in *)stream;
7611 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007612 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007613 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007614
7615 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007616
7617 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007618 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007619
7620 lock_input_stream(in);
7621 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007622 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007623
Zhou Song62ea0282020-03-22 19:53:01 +08007624 is_ha_usecase = adev->ha_proxy_enable ?
7625 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7626 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7627 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007628 && adev->voice_tx_output != NULL) {
7629 /* Use the rx device from afe-proxy record to route voice call because
7630 there is no routing if tx device is on primary hal and rx device
7631 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007632 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007633
7634 if (!voice_is_call_state_active(adev)) {
7635 if (adev->mode == AUDIO_MODE_IN_CALL) {
7636 adev->current_call_output = adev->voice_tx_output;
7637 error = voice_start_call(adev);
7638 if (error != 0)
7639 ALOGE("%s: start voice call failed %d", __func__, error);
7640 }
7641 } else {
7642 adev->current_call_output = adev->voice_tx_output;
7643 voice_update_devices_for_all_voice_usecases(adev);
7644 }
7645 }
7646
7647 pthread_mutex_unlock(&adev->lock);
7648 pthread_mutex_unlock(&in->lock);
7649}
7650
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307651int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007652 audio_io_handle_t handle,
7653 audio_devices_t devices,
7654 audio_output_flags_t flags,
7655 struct audio_config *config,
7656 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007657 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007658{
7659 struct audio_device *adev = (struct audio_device *)dev;
7660 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307661 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007662 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007663 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307664 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007665 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7666 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7667 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7668 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007669 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007670 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7671 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007672 bool force_haptic_path =
7673 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007674 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007675
kunleizdff872d2018-08-20 14:40:33 +08007676 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007677 is_usb_dev = false;
7678 devices = AUDIO_DEVICE_OUT_SPEAKER;
7679 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7680 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007681 if (config->format == AUDIO_FORMAT_DEFAULT)
7682 config->format = AUDIO_FORMAT_PCM_16_BIT;
7683 if (config->sample_rate == 0)
7684 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7685 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7686 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007687 }
7688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007689 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307690
Rahul Sharma99770982019-03-06 17:05:26 +05307691 pthread_mutex_lock(&adev->lock);
7692 if (out_get_stream(adev, handle) != NULL) {
7693 ALOGW("%s, output stream already opened", __func__);
7694 ret = -EEXIST;
7695 }
7696 pthread_mutex_unlock(&adev->lock);
7697 if (ret)
7698 return ret;
7699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007700 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7701
Mingming Yin3a941d42016-02-17 18:08:05 -08007702 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007703 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7704 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307705
7706
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007707 if (!out) {
7708 return -ENOMEM;
7709 }
7710
Haynes Mathew George204045b2015-02-25 20:32:03 -08007711 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007712 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307713 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007714 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007715 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007717 if (devices == AUDIO_DEVICE_NONE)
7718 devices = AUDIO_DEVICE_OUT_SPEAKER;
7719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007720 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007721 list_init(&out->device_list);
7722 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007723 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007724 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007725 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307726 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307727 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7728 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7729 else
7730 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007731 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007732 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007733 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307734 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307735 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307736 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007737 out->hal_output_suspend_supported = 0;
7738 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307739 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307740 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307741 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007742 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007743
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307744 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307745 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007746 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7747
Aalique Grahame22e49102018-12-18 14:23:57 -08007748 if (direct_dev &&
7749 (audio_is_linear_pcm(out->format) ||
7750 config->format == AUDIO_FORMAT_DEFAULT) &&
7751 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7752 audio_format_t req_format = config->format;
7753 audio_channel_mask_t req_channel_mask = config->channel_mask;
7754 uint32_t req_sample_rate = config->sample_rate;
7755
7756 pthread_mutex_lock(&adev->lock);
7757 if (is_hdmi) {
7758 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7759 ret = read_hdmi_sink_caps(out);
7760 if (config->sample_rate == 0)
7761 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7762 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7763 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7764 if (config->format == AUDIO_FORMAT_DEFAULT)
7765 config->format = AUDIO_FORMAT_PCM_16_BIT;
7766 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007767 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7768 &config->format,
7769 &out->supported_formats[0],
7770 MAX_SUPPORTED_FORMATS,
7771 &config->channel_mask,
7772 &out->supported_channel_masks[0],
7773 MAX_SUPPORTED_CHANNEL_MASKS,
7774 &config->sample_rate,
7775 &out->supported_sample_rates[0],
7776 MAX_SUPPORTED_SAMPLE_RATES);
7777 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007778 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007779
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007780 pthread_mutex_unlock(&adev->lock);
7781 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007782 if (ret == -ENOSYS) {
7783 /* ignore and go with default */
7784 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007785 }
7786 // For MMAP NO IRQ, allow conversions in ADSP
7787 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7788 goto error_open;
7789 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007790 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007791 goto error_open;
7792 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007793
7794 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7795 config->sample_rate = req_sample_rate;
7796 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7797 config->channel_mask = req_channel_mask;
7798 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7799 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007800 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007801
7802 out->sample_rate = config->sample_rate;
7803 out->channel_mask = config->channel_mask;
7804 out->format = config->format;
7805 if (is_hdmi) {
7806 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7807 out->config = pcm_config_hdmi_multi;
7808 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7809 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7810 out->config = pcm_config_mmap_playback;
7811 out->stream.start = out_start;
7812 out->stream.stop = out_stop;
7813 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7814 out->stream.get_mmap_position = out_get_mmap_position;
7815 } else {
7816 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7817 out->config = pcm_config_hifi;
7818 }
7819
7820 out->config.rate = out->sample_rate;
7821 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7822 if (is_hdmi) {
7823 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7824 audio_bytes_per_sample(out->format));
7825 }
7826 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007827 }
7828
Derek Chenf6318be2017-06-12 17:16:24 -04007829 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007830 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007831 /* extract car audio stream index */
7832 out->car_audio_stream =
7833 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7834 if (out->car_audio_stream < 0) {
7835 ALOGE("%s: invalid car audio stream %x",
7836 __func__, out->car_audio_stream);
7837 ret = -EINVAL;
7838 goto error_open;
7839 }
Derek Chen5f67a942020-02-24 23:08:13 -08007840 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007841 }
7842
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007843 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007844 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007845 if (!voice_extn_is_compress_voip_supported()) {
7846 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7847 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007848 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307849 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007850 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7851 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007852 out->volume_l = INVALID_OUT_VOLUME;
7853 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007854
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007855 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007856 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007857 uint32_t channel_count =
7858 audio_channel_count_from_out_mask(out->channel_mask);
7859 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7860 out->sample_rate, out->format,
7861 channel_count, false);
7862 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7863 if (frame_size != 0)
7864 out->config.period_size = buffer_size / frame_size;
7865 else
7866 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007867 }
7868 } else {
7869 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7870 voice_extn_compress_voip_is_active(out->dev)) &&
7871 (voice_extn_compress_voip_is_config_supported(config))) {
7872 ret = voice_extn_compress_voip_open_output_stream(out);
7873 if (ret != 0) {
7874 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7875 __func__, ret);
7876 goto error_open;
7877 }
Sujin Panicker19027262019-09-16 18:28:06 +05307878 } else {
7879 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7880 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007881 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007882 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007883 } else if (audio_is_linear_pcm(out->format) &&
7884 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7885 out->channel_mask = config->channel_mask;
7886 out->sample_rate = config->sample_rate;
7887 out->format = config->format;
7888 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7889 // does this change?
7890 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7891 out->config.rate = config->sample_rate;
7892 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7893 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7894 audio_bytes_per_sample(config->format));
7895 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007896 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307897 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307898 pthread_mutex_lock(&adev->lock);
7899 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7900 pthread_mutex_unlock(&adev->lock);
7901
7902 // reject offload during card offline to allow
7903 // fallback to s/w paths
7904 if (offline) {
7905 ret = -ENODEV;
7906 goto error_open;
7907 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007908
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007909 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7910 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7911 ALOGE("%s: Unsupported Offload information", __func__);
7912 ret = -EINVAL;
7913 goto error_open;
7914 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007915
Atul Khare3fa6e542017-08-09 00:56:17 +05307916 if (config->offload_info.format == 0)
7917 config->offload_info.format = config->format;
7918 if (config->offload_info.sample_rate == 0)
7919 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007920
Mingming Yin90310102013-11-13 16:57:00 -08007921 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307922 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007923 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007924 ret = -EINVAL;
7925 goto error_open;
7926 }
7927
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007928 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7929 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7930 (audio_extn_passthru_is_passthrough_stream(out)) &&
7931 !((config->sample_rate == 48000) ||
7932 (config->sample_rate == 96000) ||
7933 (config->sample_rate == 192000))) {
7934 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7935 __func__, config->sample_rate, config->offload_info.format);
7936 ret = -EINVAL;
7937 goto error_open;
7938 }
7939
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007940 out->compr_config.codec = (struct snd_codec *)
7941 calloc(1, sizeof(struct snd_codec));
7942
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007943 if (!out->compr_config.codec) {
7944 ret = -ENOMEM;
7945 goto error_open;
7946 }
7947
Dhananjay Kumarac341582017-02-23 23:42:25 +05307948 out->stream.pause = out_pause;
7949 out->stream.resume = out_resume;
7950 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307951 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307952 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007953 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307954 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007955 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307956 } else {
7957 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7958 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007959 }
vivek mehta446c3962015-09-14 10:57:35 -07007960
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307961 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7962 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007963#ifdef AUDIO_GKI_ENABLED
7964 /* out->compr_config.codec->reserved[1] is for flags */
7965 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7966#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307967 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007968#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307969 }
7970
vivek mehta446c3962015-09-14 10:57:35 -07007971 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007972 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007973 config->format == 0 && config->sample_rate == 0 &&
7974 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007975 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007976 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7977 } else {
7978 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7979 ret = -EEXIST;
7980 goto error_open;
7981 }
vivek mehta446c3962015-09-14 10:57:35 -07007982 }
7983
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007984 if (config->offload_info.channel_mask)
7985 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007986 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007987 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007988 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007989 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307990 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007991 ret = -EINVAL;
7992 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007993 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007994
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007995 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007996 out->sample_rate = config->offload_info.sample_rate;
7997
Mingming Yin3ee55c62014-08-04 14:23:35 -07007998 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007999
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308000 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05308001 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308002 audio_extn_dolby_send_ddp_endp_params(adev);
8003 audio_extn_dolby_set_dmid(adev);
8004 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008005
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008006 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008007 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008008 out->compr_config.codec->bit_rate =
8009 config->offload_info.bit_rate;
8010 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308011 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008012 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308013 /* Update bit width only for non passthrough usecases.
8014 * For passthrough usecases, the output will always be opened @16 bit
8015 */
8016 if (!audio_extn_passthru_is_passthrough_stream(out))
8017 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308018
8019 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008020#ifdef AUDIO_GKI_ENABLED
8021 /* out->compr_config.codec->reserved[1] is for flags */
8022 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8023 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8024#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308025 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8026 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008027#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308028
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008029 /*TODO: Do we need to change it for passthrough */
8030 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008031
Manish Dewangana6fc5442015-08-24 20:30:31 +05308032 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8033 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308034 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308035 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308036 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8037 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308038
8039 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8040 AUDIO_FORMAT_PCM) {
8041
8042 /*Based on platform support, configure appropriate alsa format for corresponding
8043 *hal input format.
8044 */
8045 out->compr_config.codec->format = hal_format_to_alsa(
8046 config->offload_info.format);
8047
Ashish Jain83a6cc22016-06-28 14:34:17 +05308048 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308049 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308050 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308051
Dhananjay Kumarac341582017-02-23 23:42:25 +05308052 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308053 *hal input format and alsa format might differ based on platform support.
8054 */
8055 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308056 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308057
8058 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8059
Deeraj Soman93155a62019-09-30 19:00:37 +05308060 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8061 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8062 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8063 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8064 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308065
Ashish Jainf1eaa582016-05-23 20:54:24 +05308066 /* Check if alsa session is configured with the same format as HAL input format,
8067 * if not then derive correct fragment size needed to accomodate the
8068 * conversion of HAL input format to alsa format.
8069 */
8070 audio_extn_utils_update_direct_pcm_fragment_size(out);
8071
8072 /*if hal input and output fragment size is different this indicates HAL input format is
8073 *not same as the alsa format
8074 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308075 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308076 /*Allocate a buffer to convert input data to the alsa configured format.
8077 *size of convert buffer is equal to the size required to hold one fragment size
8078 *worth of pcm data, this is because flinger does not write more than fragment_size
8079 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308080 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8081 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308082 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8083 ret = -ENOMEM;
8084 goto error_open;
8085 }
8086 }
8087 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8088 out->compr_config.fragment_size =
8089 audio_extn_passthru_get_buffer_size(&config->offload_info);
8090 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8091 } else {
8092 out->compr_config.fragment_size =
8093 platform_get_compress_offload_buffer_size(&config->offload_info);
8094 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8095 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008096
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308097 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8098 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8099 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07008100 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308101 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008102
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308103 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8104 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8105 }
8106
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008107 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8108 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008109
Manish Dewangan69426c82017-01-30 17:35:36 +05308110 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8111 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8112 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8113 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8114 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8115 } else {
8116 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8117 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008118
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308119 memset(&out->channel_map_param, 0,
8120 sizeof(struct audio_out_channel_map_param));
8121
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008122 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308123 out->send_next_track_params = false;
8124 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008125 out->offload_state = OFFLOAD_STATE_IDLE;
8126 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008127 out->writeAt.tv_sec = 0;
8128 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008129
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008130 audio_extn_dts_create_state_notifier_node(out->usecase);
8131
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008132 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8133 __func__, config->offload_info.version,
8134 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308135
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308136 /* Check if DSD audio format is supported in codec
8137 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308138 */
8139
8140 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308141 (!platform_check_codec_dsd_support(adev->platform) ||
8142 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308143 ret = -EINVAL;
8144 goto error_open;
8145 }
8146
Ashish Jain5106d362016-05-11 19:23:33 +05308147 /* Disable gapless if any of the following is true
8148 * passthrough playback
8149 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308150 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308151 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308152 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308153 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008154 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308155 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308156 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308157 check_and_set_gapless_mode(adev, false);
8158 } else
8159 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008160
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308161 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008162 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8163 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308164 if (config->format == AUDIO_FORMAT_DSD) {
8165 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008166#ifdef AUDIO_GKI_ENABLED
8167 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8168 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8169#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308170 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008171#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308172 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008173
8174 create_offload_callback_thread(out);
8175
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008176 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008177 switch (config->sample_rate) {
8178 case 0:
8179 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8180 break;
8181 case 8000:
8182 case 16000:
8183 case 48000:
8184 out->sample_rate = config->sample_rate;
8185 break;
8186 default:
8187 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8188 config->sample_rate);
8189 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8190 ret = -EINVAL;
8191 goto error_open;
8192 }
8193 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8194 switch (config->channel_mask) {
8195 case AUDIO_CHANNEL_NONE:
8196 case AUDIO_CHANNEL_OUT_STEREO:
8197 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8198 break;
8199 default:
8200 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8201 config->channel_mask);
8202 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8203 ret = -EINVAL;
8204 goto error_open;
8205 }
8206 switch (config->format) {
8207 case AUDIO_FORMAT_DEFAULT:
8208 case AUDIO_FORMAT_PCM_16_BIT:
8209 out->format = AUDIO_FORMAT_PCM_16_BIT;
8210 break;
8211 default:
8212 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8213 config->format);
8214 config->format = AUDIO_FORMAT_PCM_16_BIT;
8215 ret = -EINVAL;
8216 goto error_open;
8217 }
8218
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308219 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008220 if (ret != 0) {
8221 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008222 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008223 goto error_open;
8224 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008225 } else if (is_single_device_type_equal(&out->device_list,
8226 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008227 switch (config->sample_rate) {
8228 case 0:
8229 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8230 break;
8231 case 8000:
8232 case 16000:
8233 case 48000:
8234 out->sample_rate = config->sample_rate;
8235 break;
8236 default:
8237 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8238 config->sample_rate);
8239 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8240 ret = -EINVAL;
8241 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008242 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008243 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8244 switch (config->channel_mask) {
8245 case AUDIO_CHANNEL_NONE:
8246 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8247 break;
8248 case AUDIO_CHANNEL_OUT_STEREO:
8249 out->channel_mask = config->channel_mask;
8250 break;
8251 default:
8252 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8253 config->channel_mask);
8254 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8255 ret = -EINVAL;
8256 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008257 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008258 switch (config->format) {
8259 case AUDIO_FORMAT_DEFAULT:
8260 out->format = AUDIO_FORMAT_PCM_16_BIT;
8261 break;
8262 case AUDIO_FORMAT_PCM_16_BIT:
8263 out->format = config->format;
8264 break;
8265 default:
8266 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8267 config->format);
8268 config->format = AUDIO_FORMAT_PCM_16_BIT;
8269 ret = -EINVAL;
8270 break;
8271 }
8272 if (ret != 0)
8273 goto error_open;
8274
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008275 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8276 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008277 out->config.rate = out->sample_rate;
8278 out->config.channels =
8279 audio_channel_count_from_out_mask(out->channel_mask);
8280 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008281 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008282 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308283 unsigned int channels = 0;
8284 /*Update config params to default if not set by the caller*/
8285 if (config->sample_rate == 0)
8286 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8287 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8288 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8289 if (config->format == AUDIO_FORMAT_DEFAULT)
8290 config->format = AUDIO_FORMAT_PCM_16_BIT;
8291
8292 channels = audio_channel_count_from_out_mask(out->channel_mask);
8293
Varun Balaraje49253e2017-07-06 19:48:56 +05308294 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8295 out->usecase = get_interactive_usecase(adev);
8296 out->config = pcm_config_low_latency;
8297 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308298 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008299 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8300 out->flags);
8301 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008302 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8303 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8304 out->config = pcm_config_mmap_playback;
8305 out->stream.start = out_start;
8306 out->stream.stop = out_stop;
8307 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8308 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308309 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8310 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008311 out->hal_output_suspend_supported =
8312 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8313 out->dynamic_pm_qos_config_supported =
8314 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8315 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008316 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8317 } else {
8318 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8319 //the mixer path will be a string similar to "low-latency-playback resume"
8320 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8321 strlcat(out->pm_qos_mixer_path,
8322 " resume", MAX_MIXER_PATH_LEN);
8323 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8324 out->pm_qos_mixer_path);
8325 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308326 out->config = pcm_config_low_latency;
8327 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8328 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8329 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308330 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8331 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8332 if (out->config.period_size <= 0) {
8333 ALOGE("Invalid configuration period size is not valid");
8334 ret = -EINVAL;
8335 goto error_open;
8336 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008337 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8338 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8339 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008340 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8341 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8342 out->config = pcm_config_haptics_audio;
8343 if (force_haptic_path)
8344 adev->haptics_config = pcm_config_haptics_audio;
8345 else
8346 adev->haptics_config = pcm_config_haptics;
8347
Meng Wangd08ce322020-04-02 08:59:20 +08008348 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008349 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8350
8351 if (force_haptic_path) {
8352 out->config.channels = 1;
8353 adev->haptics_config.channels = 1;
8354 } else
8355 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 -08008356 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008357 ret = audio_extn_auto_hal_open_output_stream(out);
8358 if (ret) {
8359 ALOGE("%s: Failed to open output stream for bus device", __func__);
8360 ret = -EINVAL;
8361 goto error_open;
8362 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308363 } else {
8364 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008365 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8366 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308367 }
8368 out->hal_ip_format = format = out->format;
8369 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8370 out->hal_op_format = pcm_format_to_hal(out->config.format);
8371 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8372 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008373 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308374 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308375 if (out->hal_ip_format != out->hal_op_format) {
8376 uint32_t buffer_size = out->config.period_size *
8377 format_to_bitwidth_table[out->hal_op_format] *
8378 out->config.channels;
8379 out->convert_buffer = calloc(1, buffer_size);
8380 if (out->convert_buffer == NULL){
8381 ALOGE("Allocation failed for convert buffer for size %d",
8382 out->compr_config.fragment_size);
8383 ret = -ENOMEM;
8384 goto error_open;
8385 }
8386 ALOGD("Convert buffer allocated of size %d", buffer_size);
8387 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008388 }
8389
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008390 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8391 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308392
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008393 /* TODO remove this hardcoding and check why width is zero*/
8394 if (out->bit_width == 0)
8395 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308396 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008397 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008398 &out->device_list, out->flags,
8399 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308400 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308401 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008402 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008403 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8404 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008405 if(adev->primary_output == NULL)
8406 adev->primary_output = out;
8407 else {
8408 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008409 ret = -EEXIST;
8410 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008411 }
8412 }
8413
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008414 /* Check if this usecase is already existing */
8415 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008416 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8417 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008418 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008419 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008420 ret = -EEXIST;
8421 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008422 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008423
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008424 pthread_mutex_unlock(&adev->lock);
8425
8426 out->stream.common.get_sample_rate = out_get_sample_rate;
8427 out->stream.common.set_sample_rate = out_set_sample_rate;
8428 out->stream.common.get_buffer_size = out_get_buffer_size;
8429 out->stream.common.get_channels = out_get_channels;
8430 out->stream.common.get_format = out_get_format;
8431 out->stream.common.set_format = out_set_format;
8432 out->stream.common.standby = out_standby;
8433 out->stream.common.dump = out_dump;
8434 out->stream.common.set_parameters = out_set_parameters;
8435 out->stream.common.get_parameters = out_get_parameters;
8436 out->stream.common.add_audio_effect = out_add_audio_effect;
8437 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8438 out->stream.get_latency = out_get_latency;
8439 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008440#ifdef NO_AUDIO_OUT
8441 out->stream.write = out_write_for_no_output;
8442#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008443 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008444#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008445 out->stream.get_render_position = out_get_render_position;
8446 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008447 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008448
Haynes Mathew George16081042017-05-31 17:16:49 -07008449 if (out->realtime)
8450 out->af_period_multiplier = af_period_multiplier;
8451 else
8452 out->af_period_multiplier = 1;
8453
Andy Hunga1f48fa2019-07-01 18:14:53 -07008454 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008456 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008457 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008458 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008459
8460 config->format = out->stream.common.get_format(&out->stream.common);
8461 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8462 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308463 register_format(out->format, out->supported_formats);
8464 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8465 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008466
Aalique Grahame22e49102018-12-18 14:23:57 -08008467 out->error_log = error_log_create(
8468 ERROR_LOG_ENTRIES,
8469 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8470
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308471 /*
8472 By locking output stream before registering, we allow the callback
8473 to update stream's state only after stream's initial state is set to
8474 adev state.
8475 */
8476 lock_output_stream(out);
8477 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8478 pthread_mutex_lock(&adev->lock);
8479 out->card_status = adev->card_status;
8480 pthread_mutex_unlock(&adev->lock);
8481 pthread_mutex_unlock(&out->lock);
8482
Aalique Grahame22e49102018-12-18 14:23:57 -08008483 stream_app_type_cfg_init(&out->app_type_cfg);
8484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008485 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308486 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008487 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008488
8489 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8490 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8491 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008492 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308493 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008494 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008495 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308496 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8497 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008498 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8499 out->usecase, PCM_PLAYBACK);
8500 hdlr_stream_cfg.flags = out->flags;
8501 hdlr_stream_cfg.type = PCM_PLAYBACK;
8502 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8503 &hdlr_stream_cfg);
8504 if (ret) {
8505 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8506 out->adsp_hdlr_stream_handle = NULL;
8507 }
8508 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308509 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8510 is_direct_passthough, false);
8511 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8512 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008513 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008514 if (ret < 0) {
8515 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8516 out->ip_hdlr_handle = NULL;
8517 }
8518 }
Derek Chenf939fb72018-11-13 13:34:41 -08008519
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008520 ret = io_streams_map_insert(adev, &out->stream.common,
8521 out->handle, AUDIO_PATCH_HANDLE_NONE);
8522 if (ret != 0)
8523 goto error_open;
8524
Derek Chenf939fb72018-11-13 13:34:41 -08008525 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8526 calloc(1, sizeof(streams_output_ctxt_t));
8527 if (out_ctxt == NULL) {
8528 ALOGE("%s fail to allocate output ctxt", __func__);
8529 ret = -ENOMEM;
8530 goto error_open;
8531 }
8532 out_ctxt->output = out;
8533
8534 pthread_mutex_lock(&adev->lock);
8535 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8536 pthread_mutex_unlock(&adev->lock);
8537
Eric Laurent994a6932013-07-17 11:51:42 -07008538 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008539 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008540
8541error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308542 if (out->convert_buffer)
8543 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008544 free(out);
8545 *stream_out = NULL;
8546 ALOGD("%s: exit: ret %d", __func__, ret);
8547 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008548}
8549
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308550void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008551 struct audio_stream_out *stream)
8552{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008553 struct stream_out *out = (struct stream_out *)stream;
8554 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008555 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008556
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008557 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308558
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008559 io_streams_map_remove(adev, out->handle);
8560
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308561 // must deregister from sndmonitor first to prevent races
8562 // between the callback and close_stream
8563 audio_extn_snd_mon_unregister_listener(out);
8564
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008565 /* close adsp hdrl session before standby */
8566 if (out->adsp_hdlr_stream_handle) {
8567 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8568 if (ret)
8569 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8570 out->adsp_hdlr_stream_handle = NULL;
8571 }
8572
Manish Dewangan21a850a2017-08-14 12:03:55 +05308573 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008574 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8575 out->ip_hdlr_handle = NULL;
8576 }
8577
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008578 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308579 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008580 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308581 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308582 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008583 if(ret != 0)
8584 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8585 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008586 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008587 out_standby(&stream->common);
8588
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008589 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008590 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008591 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008592 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008593 if (out->compr_config.codec != NULL)
8594 free(out->compr_config.codec);
8595 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008596
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308597 out->a2dp_compress_mute = false;
8598
Varun Balaraje49253e2017-07-06 19:48:56 +05308599 if (is_interactive_usecase(out->usecase))
8600 free_interactive_usecase(adev, out->usecase);
8601
Ashish Jain83a6cc22016-06-28 14:34:17 +05308602 if (out->convert_buffer != NULL) {
8603 free(out->convert_buffer);
8604 out->convert_buffer = NULL;
8605 }
8606
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008607 if (adev->voice_tx_output == out)
8608 adev->voice_tx_output = NULL;
8609
Aalique Grahame22e49102018-12-18 14:23:57 -08008610 error_log_destroy(out->error_log);
8611 out->error_log = NULL;
8612
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308613 if (adev->primary_output == out)
8614 adev->primary_output = NULL;
8615
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008616 pthread_cond_destroy(&out->cond);
8617 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008618
8619 pthread_mutex_lock(&adev->lock);
8620 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8621 if (out_ctxt != NULL) {
8622 list_remove(&out_ctxt->list);
8623 free(out_ctxt);
8624 } else {
8625 ALOGW("%s, output stream already closed", __func__);
8626 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008627 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008628 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008629 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008630}
8631
8632static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8633{
8634 struct audio_device *adev = (struct audio_device *)dev;
8635 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008636 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008637 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008638 int ret;
8639 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008640 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008641 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008642 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008643
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008644 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008645 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008646
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308647 if (!parms)
8648 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308649
Derek Chen6f293672019-04-01 01:40:24 -07008650 /* notify adev and input/output streams on the snd card status */
8651 adev_snd_mon_cb((void *)adev, parms);
8652
8653 list_for_each(node, &adev->active_outputs_list) {
8654 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8655 streams_output_ctxt_t,
8656 list);
8657 out_snd_mon_cb((void *)out_ctxt->output, parms);
8658 }
8659
8660 list_for_each(node, &adev->active_inputs_list) {
8661 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8662 streams_input_ctxt_t,
8663 list);
8664 in_snd_mon_cb((void *)in_ctxt->input, parms);
8665 }
8666
Zhou Songd6d71752019-05-21 18:08:51 +08008667 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308668 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8669 if (ret >= 0) {
8670 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008671 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308672 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008673 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308674 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008675 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008676 }
8677 }
8678
8679 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8680 if (ret>=0) {
8681 if (!strncmp(value, "false", 5) &&
8682 audio_extn_a2dp_source_is_suspended()) {
8683 struct audio_usecase *usecase;
8684 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008685 list_for_each(node, &adev->usecase_list) {
8686 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008687 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008688 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008689 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008690 reassign_device_list(&usecase->stream.in->device_list,
8691 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008692 select_devices(adev, usecase->id);
8693 }
Zhou Songd6d71752019-05-21 18:08:51 +08008694 }
8695 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308696 }
8697
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008698 status = voice_set_parameters(adev, parms);
8699 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008700 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008701
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008702 status = platform_set_parameters(adev->platform, parms);
8703 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008704 goto done;
8705
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008706 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8707 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008708 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008709 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8710 adev->bluetooth_nrec = true;
8711 else
8712 adev->bluetooth_nrec = false;
8713 }
8714
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008715 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8716 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008717 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8718 adev->screen_off = false;
8719 else
8720 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008721 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008722 }
8723
Eric Laurent4b084132018-10-19 17:33:43 -07008724 ret = str_parms_get_int(parms, "rotation", &val);
8725 if (ret >= 0) {
8726 bool reverse_speakers = false;
8727 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8728 switch (val) {
8729 // FIXME: note that the code below assumes that the speakers are in the correct placement
8730 // relative to the user when the device is rotated 90deg from its default rotation. This
8731 // assumption is device-specific, not platform-specific like this code.
8732 case 270:
8733 reverse_speakers = true;
8734 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8735 break;
8736 case 0:
8737 case 180:
8738 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8739 break;
8740 case 90:
8741 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8742 break;
8743 default:
8744 ALOGE("%s: unexpected rotation of %d", __func__, val);
8745 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008746 }
Eric Laurent4b084132018-10-19 17:33:43 -07008747 if (status == 0) {
8748 // check and set swap
8749 // - check if orientation changed and speaker active
8750 // - set rotation and cache the rotation value
8751 adev->camera_orientation =
8752 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8753 if (!audio_extn_is_maxx_audio_enabled())
8754 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8755 }
8756 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008757
Mingming Yin514a8bc2014-07-29 15:22:21 -07008758 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8759 if (ret >= 0) {
8760 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8761 adev->bt_wb_speech_enabled = true;
8762 else
8763 adev->bt_wb_speech_enabled = false;
8764 }
8765
Zhou Song12c29502019-03-16 10:37:18 +08008766 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8767 if (ret >= 0) {
8768 val = atoi(value);
8769 adev->swb_speech_mode = val;
8770 }
8771
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008772 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8773 if (ret >= 0) {
8774 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308775 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008776 if (audio_is_output_device(val) &&
8777 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008778 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008779 platform_get_controller_stream_from_params(parms, &controller, &stream);
8780 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8781 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008782 if (ret < 0) {
8783 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308784 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008785 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008786 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308787 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008788 /*
8789 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8790 * Per AudioPolicyManager, USB device is higher priority than WFD.
8791 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8792 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8793 * starting voice call on USB
8794 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008795 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308796 if (ret >= 0)
8797 audio_extn_usb_add_device(device, atoi(value));
8798
Zhou Song6f862822017-11-06 17:27:57 +08008799 if (!audio_extn_usb_is_tunnel_supported()) {
8800 ALOGV("detected USB connect .. disable proxy");
8801 adev->allow_afe_proxy_usage = false;
8802 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008803 }
8804 }
8805
8806 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8807 if (ret >= 0) {
8808 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308809 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008810 /*
8811 * The HDMI / Displayport disconnect handling has been moved to
8812 * audio extension to ensure that its parameters are not
8813 * invalidated prior to updating sysfs of the disconnect event
8814 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8815 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308816 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008817 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308818 if (ret >= 0)
8819 audio_extn_usb_remove_device(device, atoi(value));
8820
Zhou Song6f862822017-11-06 17:27:57 +08008821 if (!audio_extn_usb_is_tunnel_supported()) {
8822 ALOGV("detected USB disconnect .. enable proxy");
8823 adev->allow_afe_proxy_usage = true;
8824 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008825 }
8826 }
8827
Aalique Grahame22e49102018-12-18 14:23:57 -08008828 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008829 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008830
8831 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008832 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308833 struct audio_usecase *usecase;
8834 struct listnode *node;
8835 list_for_each(node, &adev->usecase_list) {
8836 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008837 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8838 continue;
8839
8840 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308841 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008842 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308843 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008844 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308845 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308846 ALOGD("Switching to speaker and muting the stream before select_devices");
8847 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308848 //force device switch to re configure encoder
8849 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308850 ALOGD("Unmuting the stream after select_devices");
8851 usecase->stream.out->a2dp_compress_mute = false;
8852 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 +05308853 audio_extn_a2dp_set_handoff_mode(false);
8854 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308855 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308856 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8857 usecase->stream.out->a2dp_compress_mute) {
8858 pthread_mutex_unlock(&adev->lock);
8859 lock_output_stream(usecase->stream.out);
8860 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008861 reassign_device_list(&usecase->stream.out->device_list,
8862 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308863 check_a2dp_restore_l(adev, usecase->stream.out, true);
8864 pthread_mutex_unlock(&usecase->stream.out->lock);
8865 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308866 }
8867 }
8868 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008869
8870 //handle vr audio setparam
8871 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8872 value, sizeof(value));
8873 if (ret >= 0) {
8874 ALOGI("Setting vr mode to be %s", value);
8875 if (!strncmp(value, "true", 4)) {
8876 adev->vr_audio_mode_enabled = true;
8877 ALOGI("Setting vr mode to true");
8878 } else if (!strncmp(value, "false", 5)) {
8879 adev->vr_audio_mode_enabled = false;
8880 ALOGI("Setting vr mode to false");
8881 } else {
8882 ALOGI("wrong vr mode set");
8883 }
8884 }
8885
Eric Laurent4b084132018-10-19 17:33:43 -07008886 //FIXME: to be replaced by proper video capture properties API
8887 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8888 if (ret >= 0) {
8889 int camera_facing = CAMERA_FACING_BACK;
8890 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8891 camera_facing = CAMERA_FACING_FRONT;
8892 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8893 camera_facing = CAMERA_FACING_BACK;
8894 else {
8895 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8896 goto done;
8897 }
8898 adev->camera_orientation =
8899 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8900 struct audio_usecase *usecase;
8901 struct listnode *node;
8902 list_for_each(node, &adev->usecase_list) {
8903 usecase = node_to_item(node, struct audio_usecase, list);
8904 struct stream_in *in = usecase->stream.in;
8905 if (usecase->type == PCM_CAPTURE && in != NULL &&
8906 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8907 select_devices(adev, in->usecase);
8908 }
8909 }
8910 }
8911
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308912 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008913done:
8914 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008915 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308916error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008917 ALOGV("%s: exit with code(%d)", __func__, status);
8918 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008919}
8920
8921static char* adev_get_parameters(const struct audio_hw_device *dev,
8922 const char *keys)
8923{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308924 ALOGD("%s:%s", __func__, keys);
8925
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008926 struct audio_device *adev = (struct audio_device *)dev;
8927 struct str_parms *reply = str_parms_create();
8928 struct str_parms *query = str_parms_create_str(keys);
8929 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308930 char value[256] = {0};
8931 int ret = 0;
8932
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008933 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008934 if (reply) {
8935 str_parms_destroy(reply);
8936 }
8937 if (query) {
8938 str_parms_destroy(query);
8939 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008940 ALOGE("adev_get_parameters: failed to create query or reply");
8941 return NULL;
8942 }
8943
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008944 //handle vr audio getparam
8945
8946 ret = str_parms_get_str(query,
8947 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8948 value, sizeof(value));
8949
8950 if (ret >= 0) {
8951 bool vr_audio_enabled = false;
8952 pthread_mutex_lock(&adev->lock);
8953 vr_audio_enabled = adev->vr_audio_mode_enabled;
8954 pthread_mutex_unlock(&adev->lock);
8955
8956 ALOGI("getting vr mode to %d", vr_audio_enabled);
8957
8958 if (vr_audio_enabled) {
8959 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8960 "true");
8961 goto exit;
8962 } else {
8963 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8964 "false");
8965 goto exit;
8966 }
8967 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008968
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008969 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008970 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008971 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008972 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008973 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08008974 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308975 pthread_mutex_unlock(&adev->lock);
8976
Naresh Tannirud7205b62014-06-20 02:54:48 +05308977exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008978 str = str_parms_to_str(reply);
8979 str_parms_destroy(query);
8980 str_parms_destroy(reply);
8981
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308982 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008983 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008984}
8985
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008986static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008987{
8988 return 0;
8989}
8990
8991static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8992{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008993 int ret;
8994 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008995
8996 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8997
Haynes Mathew George5191a852013-09-11 14:19:36 -07008998 pthread_mutex_lock(&adev->lock);
8999 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07009000 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07009001 pthread_mutex_unlock(&adev->lock);
9002 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009003}
9004
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009005static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9006 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009007{
9008 return -ENOSYS;
9009}
9010
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009011static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9012 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009013{
9014 return -ENOSYS;
9015}
9016
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009017static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9018 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009019{
9020 return -ENOSYS;
9021}
9022
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009023static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9024 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009025{
9026 return -ENOSYS;
9027}
9028
9029static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9030{
9031 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009032 struct listnode *node;
9033 struct audio_usecase *usecase = NULL;
9034 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009036 pthread_mutex_lock(&adev->lock);
9037 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309038 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9039 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009040 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05309041 if( mode == AUDIO_MODE_CALL_SCREEN ){
9042 adev->current_call_output = adev->primary_output;
9043 voice_start_call(adev);
9044 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009045 (mode == AUDIO_MODE_NORMAL ||
9046 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009047 list_for_each(node, &adev->usecase_list) {
9048 usecase = node_to_item(node, struct audio_usecase, list);
9049 if (usecase->type == VOICE_CALL)
9050 break;
9051 }
9052 if (usecase &&
9053 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9054 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9055 true);
9056 if (ret != 0) {
9057 /* default service interval was successfully updated,
9058 reopen USB backend with new service interval */
9059 check_usecases_codec_backend(adev,
9060 usecase,
9061 usecase->out_snd_device);
9062 }
9063 }
9064
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009065 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009066 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009067 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009068 // restore device for other active usecases after stop call
9069 list_for_each(node, &adev->usecase_list) {
9070 usecase = node_to_item(node, struct audio_usecase, list);
9071 select_devices(adev, usecase->id);
9072 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009073 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009074 }
9075 pthread_mutex_unlock(&adev->lock);
9076 return 0;
9077}
9078
9079static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9080{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009081 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009082 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009083
9084 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009085 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009086 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009087
Derek Chend2530072014-11-24 12:39:14 -08009088 if (adev->ext_hw_plugin)
9089 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009090
9091 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009092 pthread_mutex_unlock(&adev->lock);
9093
9094 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009095}
9096
9097static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9098{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009099 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009100 return 0;
9101}
9102
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009103static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009104 const struct audio_config *config)
9105{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009106 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009107
Aalique Grahame22e49102018-12-18 14:23:57 -08009108 /* Don't know if USB HIFI in this context so use true to be conservative */
9109 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9110 true /*is_usb_hifi */) != 0)
9111 return 0;
9112
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009113 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9114 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009115}
9116
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009117static bool adev_input_allow_hifi_record(struct audio_device *adev,
9118 audio_devices_t devices,
9119 audio_input_flags_t flags,
9120 audio_source_t source) {
9121 const bool allowed = true;
9122
9123 if (!audio_is_usb_in_device(devices))
9124 return !allowed;
9125
9126 switch (flags) {
9127 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009128 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009129 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9130 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009131 default:
9132 return !allowed;
9133 }
9134
9135 switch (source) {
9136 case AUDIO_SOURCE_DEFAULT:
9137 case AUDIO_SOURCE_MIC:
9138 case AUDIO_SOURCE_UNPROCESSED:
9139 break;
9140 default:
9141 return !allowed;
9142 }
9143
9144 switch (adev->mode) {
9145 case 0:
9146 break;
9147 default:
9148 return !allowed;
9149 }
9150
9151 return allowed;
9152}
9153
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009154static int adev_update_voice_comm_input_stream(struct stream_in *in,
9155 struct audio_config *config)
9156{
9157 bool valid_rate = (config->sample_rate == 8000 ||
9158 config->sample_rate == 16000 ||
9159 config->sample_rate == 32000 ||
9160 config->sample_rate == 48000);
9161 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9162
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009163 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009164 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009165 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9166 in->config = default_pcm_config_voip_copp;
9167 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9168 DEFAULT_VOIP_BUF_DURATION_MS,
9169 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009170 } else {
9171 ALOGW("%s No valid input in voip, use defaults"
9172 "sample rate %u, channel mask 0x%X",
9173 __func__, config->sample_rate, in->channel_mask);
9174 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009175 in->config.rate = config->sample_rate;
9176 in->sample_rate = config->sample_rate;
9177 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009178 //XXX needed for voice_extn_compress_voip_open_input_stream
9179 in->config.rate = config->sample_rate;
9180 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309181 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009182 voice_extn_compress_voip_is_active(in->dev)) &&
9183 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9184 valid_rate && valid_ch) {
9185 voice_extn_compress_voip_open_input_stream(in);
9186 // update rate entries to match config from AF
9187 in->config.rate = config->sample_rate;
9188 in->sample_rate = config->sample_rate;
9189 } else {
9190 ALOGW("%s compress voip not active, use defaults", __func__);
9191 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009192 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009193 return 0;
9194}
9195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009196static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009197 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009198 audio_devices_t devices,
9199 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009200 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309201 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009202 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009203 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009204{
9205 struct audio_device *adev = (struct audio_device *)dev;
9206 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009207 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009208 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009209 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309210 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009211 bool is_usb_dev = audio_is_usb_in_device(devices);
9212 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9213 devices,
9214 flags,
9215 source);
Andy Hung94320602018-10-29 18:31:12 -07009216 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9217 " sample_rate %u, channel_mask %#x, format %#x",
9218 __func__, flags, is_usb_dev, may_use_hifi_record,
9219 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309220
kunleizdff872d2018-08-20 14:40:33 +08009221 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009222 is_usb_dev = false;
9223 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9224 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9225 __func__, devices);
9226 }
9227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009228 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009229
9230 if (!(is_usb_dev && may_use_hifi_record)) {
9231 if (config->sample_rate == 0)
9232 config->sample_rate = 48000;
9233 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9234 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9235 if (config->format == AUDIO_FORMAT_DEFAULT)
9236 config->format = AUDIO_FORMAT_PCM_16_BIT;
9237
9238 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9239
Aalique Grahame22e49102018-12-18 14:23:57 -08009240 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9241 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009242 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309243 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009244
Rahul Sharma99770982019-03-06 17:05:26 +05309245 pthread_mutex_lock(&adev->lock);
9246 if (in_get_stream(adev, handle) != NULL) {
9247 ALOGW("%s, input stream already opened", __func__);
9248 ret = -EEXIST;
9249 }
9250 pthread_mutex_unlock(&adev->lock);
9251 if (ret)
9252 return ret;
9253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009254 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009255
9256 if (!in) {
9257 ALOGE("failed to allocate input stream");
9258 return -ENOMEM;
9259 }
9260
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309261 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309262 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9263 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009264 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009265 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009267 in->stream.common.get_sample_rate = in_get_sample_rate;
9268 in->stream.common.set_sample_rate = in_set_sample_rate;
9269 in->stream.common.get_buffer_size = in_get_buffer_size;
9270 in->stream.common.get_channels = in_get_channels;
9271 in->stream.common.get_format = in_get_format;
9272 in->stream.common.set_format = in_set_format;
9273 in->stream.common.standby = in_standby;
9274 in->stream.common.dump = in_dump;
9275 in->stream.common.set_parameters = in_set_parameters;
9276 in->stream.common.get_parameters = in_get_parameters;
9277 in->stream.common.add_audio_effect = in_add_audio_effect;
9278 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9279 in->stream.set_gain = in_set_gain;
9280 in->stream.read = in_read;
9281 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009282 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309283 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009284 in->stream.set_microphone_direction = in_set_microphone_direction;
9285 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009286 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009287
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009288 list_init(&in->device_list);
9289 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009290 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009291 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009292 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009293 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009294 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009295 in->bit_width = 16;
9296 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009297 in->direction = MIC_DIRECTION_UNSPECIFIED;
9298 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009299 list_init(&in->aec_list);
9300 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009301 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009302
Andy Hung94320602018-10-29 18:31:12 -07009303 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009304 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9305 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9306 /* Force channel config requested to mono if incall
9307 record is being requested for only uplink/downlink */
9308 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9309 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9310 ret = -EINVAL;
9311 goto err_open;
9312 }
9313 }
9314
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009315 if (is_usb_dev && may_use_hifi_record) {
9316 /* HiFi record selects an appropriate format, channel, rate combo
9317 depending on sink capabilities*/
9318 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9319 &config->format,
9320 &in->supported_formats[0],
9321 MAX_SUPPORTED_FORMATS,
9322 &config->channel_mask,
9323 &in->supported_channel_masks[0],
9324 MAX_SUPPORTED_CHANNEL_MASKS,
9325 &config->sample_rate,
9326 &in->supported_sample_rates[0],
9327 MAX_SUPPORTED_SAMPLE_RATES);
9328 if (ret != 0) {
9329 ret = -EINVAL;
9330 goto err_open;
9331 }
9332 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009333 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309334 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309335 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9336 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9337 in->config.format = PCM_FORMAT_S32_LE;
9338 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309339 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9340 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9341 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9342 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9343 bool ret_error = false;
9344 in->bit_width = 24;
9345 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9346 from HAL is 24_packed and 8_24
9347 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9348 24_packed return error indicating supported format is 24_packed
9349 *> In case of any other source requesting 24 bit or float return error
9350 indicating format supported is 16 bit only.
9351
9352 on error flinger will retry with supported format passed
9353 */
9354 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9355 (source != AUDIO_SOURCE_CAMCORDER)) {
9356 config->format = AUDIO_FORMAT_PCM_16_BIT;
9357 if (config->sample_rate > 48000)
9358 config->sample_rate = 48000;
9359 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009360 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9361 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309362 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9363 ret_error = true;
9364 }
9365
9366 if (ret_error) {
9367 ret = -EINVAL;
9368 goto err_open;
9369 }
9370 }
9371
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009372 in->channel_mask = config->channel_mask;
9373 in->format = config->format;
9374
9375 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309376
9377 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9378 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9379 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9380 else {
9381 ret = -EINVAL;
9382 goto err_open;
9383 }
9384 }
9385
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009386 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309387 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9388 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009389 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9390 is_low_latency = true;
9391#if LOW_LATENCY_CAPTURE_USE_CASE
9392 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9393#endif
9394 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009395 if (!in->realtime) {
9396 in->config = pcm_config_audio_capture;
9397 frame_size = audio_stream_in_frame_size(&in->stream);
9398 buffer_size = get_input_buffer_size(config->sample_rate,
9399 config->format,
9400 channel_count,
9401 is_low_latency);
9402 in->config.period_size = buffer_size / frame_size;
9403 in->config.rate = config->sample_rate;
9404 in->af_period_multiplier = 1;
9405 } else {
9406 // period size is left untouched for rt mode playback
9407 in->config = pcm_config_audio_capture_rt;
9408 in->af_period_multiplier = af_period_multiplier;
9409 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009410 }
9411
9412 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9413 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9414 in->realtime = 0;
9415 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9416 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009417 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009418 in->stream.start = in_start;
9419 in->stream.stop = in_stop;
9420 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9421 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009422 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009423 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009424 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9425 in->config = pcm_config_audio_capture;
9426 frame_size = audio_stream_in_frame_size(&in->stream);
9427 buffer_size = get_input_buffer_size(config->sample_rate,
9428 config->format,
9429 channel_count,
9430 false /*is_low_latency*/);
9431 in->config.period_size = buffer_size / frame_size;
9432 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009433 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009434 switch (config->format) {
9435 case AUDIO_FORMAT_PCM_32_BIT:
9436 in->bit_width = 32;
9437 break;
9438 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9439 case AUDIO_FORMAT_PCM_8_24_BIT:
9440 in->bit_width = 24;
9441 break;
9442 default:
9443 in->bit_width = 16;
9444 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009445 } else if (is_single_device_type_equal(&in->device_list,
9446 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9447 is_single_device_type_equal(&in->device_list,
9448 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009449 if (config->sample_rate == 0)
9450 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9451 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9452 config->sample_rate != 8000) {
9453 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9454 ret = -EINVAL;
9455 goto err_open;
9456 }
9457 if (config->format == AUDIO_FORMAT_DEFAULT)
9458 config->format = AUDIO_FORMAT_PCM_16_BIT;
9459 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9460 config->format = AUDIO_FORMAT_PCM_16_BIT;
9461 ret = -EINVAL;
9462 goto err_open;
9463 }
9464
9465 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009466 if (adev->ha_proxy_enable &&
9467 is_single_device_type_equal(&in->device_list,
9468 AUDIO_DEVICE_IN_TELEPHONY_RX))
9469 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009470 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009471 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009472 in->af_period_multiplier = 1;
9473 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9474 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9475 (config->sample_rate == 8000 ||
9476 config->sample_rate == 16000 ||
9477 config->sample_rate == 32000 ||
9478 config->sample_rate == 48000) &&
9479 channel_count == 1) {
9480 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9481 in->config = pcm_config_audio_capture;
9482 frame_size = audio_stream_in_frame_size(&in->stream);
9483 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9484 config->sample_rate,
9485 config->format,
9486 channel_count, false /*is_low_latency*/);
9487 in->config.period_size = buffer_size / frame_size;
9488 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9489 in->config.rate = config->sample_rate;
9490 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009491 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309492 int ret_val;
9493 pthread_mutex_lock(&adev->lock);
9494 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9495 in, config, &channel_mask_updated);
9496 pthread_mutex_unlock(&adev->lock);
9497
9498 if (!ret_val) {
9499 if (channel_mask_updated == true) {
9500 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9501 __func__, config->channel_mask);
9502 ret = -EINVAL;
9503 goto err_open;
9504 }
9505 ALOGD("%s: created multi-channel session succesfully",__func__);
9506 } else if (audio_extn_compr_cap_enabled() &&
9507 audio_extn_compr_cap_format_supported(config->format) &&
9508 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9509 audio_extn_compr_cap_init(in);
9510 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309511 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309512 if (ret)
9513 goto err_open;
9514 } else {
9515 in->config = pcm_config_audio_capture;
9516 in->config.rate = config->sample_rate;
9517 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309518 in->format = config->format;
9519 frame_size = audio_stream_in_frame_size(&in->stream);
9520 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009521 config->format,
9522 channel_count,
9523 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009524 /* prevent division-by-zero */
9525 if (frame_size == 0) {
9526 ALOGE("%s: Error frame_size==0", __func__);
9527 ret = -EINVAL;
9528 goto err_open;
9529 }
9530
Revathi Uddarajud2634032017-12-07 14:42:34 +05309531 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009532 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009533
Revathi Uddarajud2634032017-12-07 14:42:34 +05309534 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9535 /* optionally use VOIP usecase depending on config(s) */
9536 ret = adev_update_voice_comm_input_stream(in, config);
9537 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009538
Revathi Uddarajud2634032017-12-07 14:42:34 +05309539 if (ret) {
9540 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9541 goto err_open;
9542 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009543 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309544
9545 /* assign concurrent capture usecase if record has to caried out from
9546 * actual hardware input source */
9547 if (audio_extn_is_concurrent_capture_enabled() &&
9548 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309549 /* Acquire lock to avoid two concurrent use cases initialized to
9550 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009551
Samyak Jainc37062f2019-04-25 18:41:06 +05309552 if (in->usecase == USECASE_AUDIO_RECORD) {
9553 pthread_mutex_lock(&adev->lock);
9554 if (!(adev->pcm_record_uc_state)) {
9555 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9556 adev->pcm_record_uc_state = 1;
9557 pthread_mutex_unlock(&adev->lock);
9558 } else {
9559 pthread_mutex_unlock(&adev->lock);
9560 /* Assign compress record use case for second record */
9561 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9562 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9563 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9564 if (audio_extn_cin_applicable_stream(in)) {
9565 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309566 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309567 if (ret)
9568 goto err_open;
9569 }
9570 }
9571 }
kunleiz28c73e72019-03-27 17:24:04 +08009572 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009573 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309574 if (audio_extn_ssr_get_stream() != in)
9575 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009576
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009577 in->sample_rate = in->config.rate;
9578
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309579 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9580 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009581 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009582 in->sample_rate, in->bit_width,
9583 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309584 register_format(in->format, in->supported_formats);
9585 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9586 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309587
Aalique Grahame22e49102018-12-18 14:23:57 -08009588 in->error_log = error_log_create(
9589 ERROR_LOG_ENTRIES,
9590 1000000000 /* aggregate consecutive identical errors within one second */);
9591
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009592 /* This stream could be for sound trigger lab,
9593 get sound trigger pcm if present */
9594 audio_extn_sound_trigger_check_and_get_session(in);
9595
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309596 lock_input_stream(in);
9597 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9598 pthread_mutex_lock(&adev->lock);
9599 in->card_status = adev->card_status;
9600 pthread_mutex_unlock(&adev->lock);
9601 pthread_mutex_unlock(&in->lock);
9602
Aalique Grahame22e49102018-12-18 14:23:57 -08009603 stream_app_type_cfg_init(&in->app_type_cfg);
9604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009605 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009606
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009607 ret = io_streams_map_insert(adev, &in->stream.common,
9608 handle, AUDIO_PATCH_HANDLE_NONE);
9609 if (ret != 0)
9610 goto err_open;
9611
Derek Chenf939fb72018-11-13 13:34:41 -08009612 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9613 calloc(1, sizeof(streams_input_ctxt_t));
9614 if (in_ctxt == NULL) {
9615 ALOGE("%s fail to allocate input ctxt", __func__);
9616 ret = -ENOMEM;
9617 goto err_open;
9618 }
9619 in_ctxt->input = in;
9620
9621 pthread_mutex_lock(&adev->lock);
9622 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9623 pthread_mutex_unlock(&adev->lock);
9624
Eric Laurent994a6932013-07-17 11:51:42 -07009625 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009626 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009627
9628err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309629 if (in->usecase == USECASE_AUDIO_RECORD) {
9630 pthread_mutex_lock(&adev->lock);
9631 adev->pcm_record_uc_state = 0;
9632 pthread_mutex_unlock(&adev->lock);
9633 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009634 free(in);
9635 *stream_in = NULL;
9636 return ret;
9637}
9638
9639static void adev_close_input_stream(struct audio_hw_device *dev,
9640 struct audio_stream_in *stream)
9641{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009642 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009643 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009644 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309645
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309646 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009647
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009648 if (in == NULL) {
9649 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9650 return;
9651 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009652 io_streams_map_remove(adev, in->capture_handle);
9653
kunleiz70e57612018-12-28 17:50:23 +08009654 /* must deregister from sndmonitor first to prevent races
9655 * between the callback and close_stream
9656 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309657 audio_extn_snd_mon_unregister_listener(stream);
9658
kunleiz70e57612018-12-28 17:50:23 +08009659 /* Disable echo reference if there are no active input, hfp call
9660 * and sound trigger while closing input stream
9661 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009662 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009663 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009664 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9665 struct listnode out_devices;
9666 list_init(&out_devices);
9667 platform_set_echo_reference(adev, false, &out_devices);
9668 } else
kunleiz70e57612018-12-28 17:50:23 +08009669 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309670
Weiyin Jiang2995f662019-04-17 14:25:12 +08009671 error_log_destroy(in->error_log);
9672 in->error_log = NULL;
9673
Pallavid7c7a272018-01-16 11:22:55 +05309674
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009675 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309676 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009677 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309678 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009679 if (ret != 0)
9680 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9681 __func__, ret);
9682 } else
9683 in_standby(&stream->common);
9684
Revathi Uddarajud2634032017-12-07 14:42:34 +05309685 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309686 if (in->usecase == USECASE_AUDIO_RECORD) {
9687 adev->pcm_record_uc_state = 0;
9688 }
9689
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009690 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9691 adev->enable_voicerx = false;
9692 }
9693
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009694 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009695 audio_extn_ssr_deinit();
9696 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009697
Garmond Leunge2433c32017-09-28 21:51:22 -07009698 if (audio_extn_ffv_get_stream() == in) {
9699 audio_extn_ffv_stream_deinit();
9700 }
9701
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309702 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009703 audio_extn_compr_cap_format_supported(in->config.format))
9704 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309705
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309706 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309707 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009708
Mingming Yinfd7607b2016-01-22 12:48:44 -08009709 if (in->is_st_session) {
9710 ALOGV("%s: sound trigger pcm stop lab", __func__);
9711 audio_extn_sound_trigger_stop_lab(in);
9712 }
Derek Chenf939fb72018-11-13 13:34:41 -08009713 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9714 if (in_ctxt != NULL) {
9715 list_remove(&in_ctxt->list);
9716 free(in_ctxt);
9717 } else {
9718 ALOGW("%s, input stream already closed", __func__);
9719 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009720 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309721 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009722 return;
9723}
9724
Aalique Grahame22e49102018-12-18 14:23:57 -08009725/* verifies input and output devices and their capabilities.
9726 *
9727 * This verification is required when enabling extended bit-depth or
9728 * sampling rates, as not all qcom products support it.
9729 *
9730 * Suitable for calling only on initialization such as adev_open().
9731 * It fills the audio_device use_case_table[] array.
9732 *
9733 * Has a side-effect that it needs to configure audio routing / devices
9734 * in order to power up the devices and read the device parameters.
9735 * It does not acquire any hw device lock. Should restore the devices
9736 * back to "normal state" upon completion.
9737 */
9738static int adev_verify_devices(struct audio_device *adev)
9739{
9740 /* enumeration is a bit difficult because one really wants to pull
9741 * the use_case, device id, etc from the hidden pcm_device_table[].
9742 * In this case there are the following use cases and device ids.
9743 *
9744 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9745 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9746 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9747 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9748 * [USECASE_AUDIO_RECORD] = {0, 0},
9749 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9750 * [USECASE_VOICE_CALL] = {2, 2},
9751 *
9752 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9753 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9754 */
9755
9756 /* should be the usecases enabled in adev_open_input_stream() */
9757 static const int test_in_usecases[] = {
9758 USECASE_AUDIO_RECORD,
9759 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9760 };
9761 /* should be the usecases enabled in adev_open_output_stream()*/
9762 static const int test_out_usecases[] = {
9763 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9764 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9765 };
9766 static const usecase_type_t usecase_type_by_dir[] = {
9767 PCM_PLAYBACK,
9768 PCM_CAPTURE,
9769 };
9770 static const unsigned flags_by_dir[] = {
9771 PCM_OUT,
9772 PCM_IN,
9773 };
9774
9775 size_t i;
9776 unsigned dir;
9777 const unsigned card_id = adev->snd_card;
9778
9779 for (dir = 0; dir < 2; ++dir) {
9780 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9781 const unsigned flags_dir = flags_by_dir[dir];
9782 const size_t testsize =
9783 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9784 const int *testcases =
9785 dir ? test_in_usecases : test_out_usecases;
9786 const audio_devices_t audio_device =
9787 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9788
9789 for (i = 0; i < testsize; ++i) {
9790 const audio_usecase_t audio_usecase = testcases[i];
9791 int device_id;
9792 struct pcm_params **pparams;
9793 struct stream_out out;
9794 struct stream_in in;
9795 struct audio_usecase uc_info;
9796 int retval;
9797
9798 pparams = &adev->use_case_table[audio_usecase];
9799 pcm_params_free(*pparams); /* can accept null input */
9800 *pparams = NULL;
9801
9802 /* find the device ID for the use case (signed, for error) */
9803 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9804 if (device_id < 0)
9805 continue;
9806
9807 /* prepare structures for device probing */
9808 memset(&uc_info, 0, sizeof(uc_info));
9809 uc_info.id = audio_usecase;
9810 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009811 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009812 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009813 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009814 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009815 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009816 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9817 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009818 }
9819 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009820 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009821 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009822 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009823 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009824 uc_info.in_snd_device = SND_DEVICE_NONE;
9825 uc_info.out_snd_device = SND_DEVICE_NONE;
9826 list_add_tail(&adev->usecase_list, &uc_info.list);
9827
9828 /* select device - similar to start_(in/out)put_stream() */
9829 retval = select_devices(adev, audio_usecase);
9830 if (retval >= 0) {
9831 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9832#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009833 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009834 if (*pparams) {
9835 ALOGV("%s: (%s) card %d device %d", __func__,
9836 dir ? "input" : "output", card_id, device_id);
9837 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9838 } else {
9839 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9840 }
9841#endif
9842 }
9843
9844 /* deselect device - similar to stop_(in/out)put_stream() */
9845 /* 1. Get and set stream specific mixer controls */
9846 retval = disable_audio_route(adev, &uc_info);
9847 /* 2. Disable the rx device */
9848 retval = disable_snd_device(adev,
9849 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9850 list_remove(&uc_info.list);
9851 }
9852 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009853 return 0;
9854}
9855
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009856int update_patch(unsigned int num_sources,
9857 const struct audio_port_config *sources,
9858 unsigned int num_sinks,
9859 const struct audio_port_config *sinks,
9860 audio_patch_handle_t handle,
9861 struct audio_patch_info *p_info,
9862 patch_type_t patch_type, bool new_patch)
9863{
9864 ALOGD("%s: enter", __func__);
9865
9866 if (p_info == NULL) {
9867 ALOGE("%s: Invalid patch pointer", __func__);
9868 return -EINVAL;
9869 }
9870
9871 if (new_patch) {
9872 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9873 if (p_info->patch == NULL) {
9874 ALOGE("%s: Could not allocate patch", __func__);
9875 return -ENOMEM;
9876 }
9877 }
9878
9879 p_info->patch->id = handle;
9880 p_info->patch->num_sources = num_sources;
9881 p_info->patch->num_sinks = num_sinks;
9882
9883 for (int i = 0; i < num_sources; i++)
9884 p_info->patch->sources[i] = sources[i];
9885 for (int i = 0; i < num_sinks; i++)
9886 p_info->patch->sinks[i] = sinks[i];
9887
9888 p_info->patch_type = patch_type;
9889 return 0;
9890}
9891
9892audio_patch_handle_t generate_patch_handle()
9893{
9894 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9895 if (++patch_handle < 0)
9896 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9897 return patch_handle;
9898}
9899
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309900int adev_create_audio_patch(struct audio_hw_device *dev,
9901 unsigned int num_sources,
9902 const struct audio_port_config *sources,
9903 unsigned int num_sinks,
9904 const struct audio_port_config *sinks,
9905 audio_patch_handle_t *handle)
9906{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009907 int ret = 0;
9908 struct audio_device *adev = (struct audio_device *)dev;
9909 struct audio_patch_info *p_info = NULL;
9910 patch_type_t patch_type = PATCH_NONE;
9911 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9912 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9913 struct audio_stream_info *s_info = NULL;
9914 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009915 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009916 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9917 bool new_patch = false;
9918 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309919
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009920 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9921 num_sources, num_sinks, *handle);
9922
9923 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9924 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9925 ALOGE("%s: Invalid patch arguments", __func__);
9926 ret = -EINVAL;
9927 goto done;
9928 }
9929
9930 if (num_sources > 1) {
9931 ALOGE("%s: Multiple sources are not supported", __func__);
9932 ret = -EINVAL;
9933 goto done;
9934 }
9935
9936 if (sources == NULL || sinks == NULL) {
9937 ALOGE("%s: Invalid sources or sinks port config", __func__);
9938 ret = -EINVAL;
9939 goto done;
9940 }
9941
9942 ALOGV("%s: source role %d, source type %d", __func__,
9943 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009944 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009945
9946 // Populate source/sink information and fetch stream info
9947 switch (sources[0].type) {
9948 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9949 device_type = sources[0].ext.device.type;
9950 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009951 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009952 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9953 patch_type = PATCH_CAPTURE;
9954 io_handle = sinks[0].ext.mix.handle;
9955 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009956 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009957 __func__, device_type, io_handle);
9958 } else {
9959 // Device to device patch is not implemented.
9960 // This space will need changes if audio HAL
9961 // handles device to device patches in the future.
9962 patch_type = PATCH_DEVICE_LOOPBACK;
9963 }
9964 break;
9965 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9966 io_handle = sources[0].ext.mix.handle;
9967 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009968 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009969 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009970 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009971 }
9972 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009973 ALOGD("%s: Playback patch from mix handle %d to device %x",
9974 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009975 break;
9976 case AUDIO_PORT_TYPE_SESSION:
9977 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009978 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9979 ret = -EINVAL;
9980 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009981 }
9982
9983 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009984
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009985 // Generate patch info and update patch
9986 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009987 *handle = generate_patch_handle();
9988 p_info = (struct audio_patch_info *)
9989 calloc(1, sizeof(struct audio_patch_info));
9990 if (p_info == NULL) {
9991 ALOGE("%s: Failed to allocate memory", __func__);
9992 pthread_mutex_unlock(&adev->lock);
9993 ret = -ENOMEM;
9994 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009995 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009996 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009997 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009998 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009999 if (p_info == NULL) {
10000 ALOGE("%s: Unable to fetch patch for received patch handle %d",
10001 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010002 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010003 ret = -EINVAL;
10004 goto done;
10005 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010006 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010007 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010008 *handle, p_info, patch_type, new_patch);
10009
10010 // Fetch stream info of associated mix for playback or capture patches
10011 if (p_info->patch_type == PATCH_PLAYBACK ||
10012 p_info->patch_type == PATCH_CAPTURE) {
10013 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10014 if (s_info == NULL) {
10015 ALOGE("%s: Failed to obtain stream info", __func__);
10016 if (new_patch)
10017 free(p_info);
10018 pthread_mutex_unlock(&adev->lock);
10019 ret = -EINVAL;
10020 goto done;
10021 }
10022 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10023 s_info->patch_handle = *handle;
10024 stream = s_info->stream;
10025 }
10026 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010027
10028 // Update routing for stream
10029 if (stream != NULL) {
10030 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010031 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010032 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010033 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010034 if (ret < 0) {
10035 pthread_mutex_lock(&adev->lock);
10036 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10037 if (new_patch)
10038 free(p_info);
10039 pthread_mutex_unlock(&adev->lock);
10040 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10041 goto done;
10042 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010043 }
10044
10045 // Add new patch to patch map
10046 if (!ret && new_patch) {
10047 pthread_mutex_lock(&adev->lock);
10048 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010049 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010050 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010051 }
10052
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010053done:
10054 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010055 num_sources,
10056 sources,
10057 num_sinks,
10058 sinks,
10059 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010060 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010061 num_sources,
10062 sources,
10063 num_sinks,
10064 sinks,
10065 handle);
10066 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010067}
10068
10069int adev_release_audio_patch(struct audio_hw_device *dev,
10070 audio_patch_handle_t handle)
10071{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010072 struct audio_device *adev = (struct audio_device *) dev;
10073 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010074 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010075 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010076
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010077 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10078 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10079 ret = -EINVAL;
10080 goto done;
10081 }
10082
10083 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010084 pthread_mutex_lock(&adev->lock);
10085 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010086 if (p_info == NULL) {
10087 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010088 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010089 ret = -EINVAL;
10090 goto done;
10091 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010092 struct audio_patch *patch = p_info->patch;
10093 if (patch == NULL) {
10094 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010095 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010096 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010097 goto done;
10098 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010099 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10100 switch (patch->sources[0].type) {
10101 case AUDIO_PORT_TYPE_MIX:
10102 io_handle = patch->sources[0].ext.mix.handle;
10103 break;
10104 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010105 if (p_info->patch_type == PATCH_CAPTURE)
10106 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010107 break;
10108 case AUDIO_PORT_TYPE_SESSION:
10109 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010110 pthread_mutex_unlock(&adev->lock);
10111 ret = -EINVAL;
10112 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010113 }
10114
10115 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010116 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010117 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010118 if (patch_type == PATCH_PLAYBACK ||
10119 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010120 struct audio_stream_info *s_info =
10121 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10122 if (s_info == NULL) {
10123 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10124 pthread_mutex_unlock(&adev->lock);
10125 goto done;
10126 }
10127 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10128 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010129 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010130 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010131
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010132 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010133 struct listnode devices;
10134 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010135 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010136 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010137 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010138 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010139 }
10140
10141 if (ret < 0)
10142 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10143
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010144done:
10145 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10146 audio_extn_auto_hal_release_audio_patch(dev, handle);
10147
10148 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010149 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010150}
10151
10152int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10153{
Derek Chenf13dd492018-11-13 14:53:51 -080010154 int ret = 0;
10155
10156 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10157 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10158 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010159}
10160
10161int adev_set_audio_port_config(struct audio_hw_device *dev,
10162 const struct audio_port_config *config)
10163{
Derek Chenf13dd492018-11-13 14:53:51 -080010164 int ret = 0;
10165
10166 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10167 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10168 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010169}
10170
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010171static int adev_dump(const audio_hw_device_t *device __unused,
10172 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010173{
10174 return 0;
10175}
10176
10177static int adev_close(hw_device_t *device)
10178{
Aalique Grahame22e49102018-12-18 14:23:57 -080010179 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010180 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010181
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010182 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010183 return 0;
10184
10185 pthread_mutex_lock(&adev_init_lock);
10186
10187 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010188 if (audio_extn_spkr_prot_is_enabled())
10189 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010190 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010191 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010192 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010193 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010194 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010195 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010196 audio_extn_utils_release_streams_cfg_lists(
10197 &adev->streams_output_cfg_list,
10198 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010199 if (audio_extn_qap_is_enabled())
10200 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010201 if (audio_extn_qaf_is_enabled())
10202 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010203 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010204 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010205 free(adev->snd_dev_ref_cnt);
10206 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010207 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10208 pcm_params_free(adev->use_case_table[i]);
10209 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010210 if (adev->adm_deinit)
10211 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010212 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010213 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010214 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010215 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010216 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010217 if (adev->device_cfg_params) {
10218 free(adev->device_cfg_params);
10219 adev->device_cfg_params = NULL;
10220 }
Derek Chend2530072014-11-24 12:39:14 -080010221 if(adev->ext_hw_plugin)
10222 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010223 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010224 free_map(adev->patch_map);
10225 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010226 free(device);
10227 adev = NULL;
10228 }
10229 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010230 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010231 return 0;
10232}
10233
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010234/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10235 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10236 * just that it _might_ work.
10237 */
10238static int period_size_is_plausible_for_low_latency(int period_size)
10239{
10240 switch (period_size) {
10241 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010242 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010243 case 240:
10244 case 320:
10245 case 480:
10246 return 1;
10247 default:
10248 return 0;
10249 }
10250}
10251
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010252static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10253{
10254 bool is_snd_card_status = false;
10255 bool is_ext_device_status = false;
10256 char value[32];
10257 int card = -1;
10258 card_status_t status;
10259
10260 if (cookie != adev || !parms)
10261 return;
10262
10263 if (!parse_snd_card_status(parms, &card, &status)) {
10264 is_snd_card_status = true;
10265 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10266 is_ext_device_status = true;
10267 } else {
10268 // not a valid event
10269 return;
10270 }
10271
10272 pthread_mutex_lock(&adev->lock);
10273 if (card == adev->snd_card || is_ext_device_status) {
10274 if (is_snd_card_status && adev->card_status != status) {
10275 adev->card_status = status;
10276 platform_snd_card_update(adev->platform, status);
10277 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010278 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010279 if (status == CARD_STATUS_OFFLINE)
10280 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010281 } else if (is_ext_device_status) {
10282 platform_set_parameters(adev->platform, parms);
10283 }
10284 }
10285 pthread_mutex_unlock(&adev->lock);
10286 return;
10287}
10288
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010289/* out and adev lock held */
10290static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10291{
10292 struct audio_usecase *uc_info;
10293 float left_p;
10294 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010295 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010296
10297 uc_info = get_usecase_from_list(adev, out->usecase);
10298 if (uc_info == NULL) {
10299 ALOGE("%s: Could not find the usecase (%d) in the list",
10300 __func__, out->usecase);
10301 return -EINVAL;
10302 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010303 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010304
10305 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10306 out->usecase, use_case_table[out->usecase]);
10307
10308 if (restore) {
10309 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010310 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010311 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010312 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10313 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010314 pthread_mutex_lock(&out->compr_mute_lock);
10315 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010316 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010317 out->a2dp_compress_mute = false;
10318 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10319 }
10320 pthread_mutex_unlock(&out->compr_mute_lock);
10321 }
10322 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010323 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10324 // mute compress stream if suspended
10325 pthread_mutex_lock(&out->compr_mute_lock);
10326 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010327 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010328 assign_devices(&devices, &out->device_list);
10329 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010330 left_p = out->volume_l;
10331 right_p = out->volume_r;
10332 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10333 compress_pause(out->compr);
10334 out_set_compr_volume(&out->stream, (float)0, (float)0);
10335 out->a2dp_compress_mute = true;
10336 select_devices(adev, out->usecase);
10337 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10338 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010339 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010340 out->volume_l = left_p;
10341 out->volume_r = right_p;
10342 }
Zhou Songc576a452019-09-09 14:17:40 +080010343 pthread_mutex_unlock(&out->compr_mute_lock);
10344 } else {
10345 // tear down a2dp path for non offloaded streams
10346 if (audio_extn_a2dp_source_is_suspended())
10347 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010348 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010349 }
10350 ALOGV("%s: exit", __func__);
10351 return 0;
10352}
10353
10354int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10355{
10356 int ret = 0;
10357
10358 lock_output_stream(out);
10359 pthread_mutex_lock(&adev->lock);
10360
10361 ret = check_a2dp_restore_l(adev, out, restore);
10362
10363 pthread_mutex_unlock(&adev->lock);
10364 pthread_mutex_unlock(&out->lock);
10365 return ret;
10366}
10367
Haynes Mathew George01156f92018-04-13 15:29:54 -070010368void adev_on_battery_status_changed(bool charging)
10369{
10370 pthread_mutex_lock(&adev->lock);
10371 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10372 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010373 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010374 pthread_mutex_unlock(&adev->lock);
10375}
10376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010377static int adev_open(const hw_module_t *module, const char *name,
10378 hw_device_t **device)
10379{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010380 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010381 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010382 char mixer_ctl_name[128] = {0};
10383 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010384
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010385 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010386 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10387
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010388 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010389 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010390 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010391 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010392 ALOGD("%s: returning existing instance of adev", __func__);
10393 ALOGD("%s: exit", __func__);
10394 pthread_mutex_unlock(&adev_init_lock);
10395 return 0;
10396 }
10397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010398 adev = calloc(1, sizeof(struct audio_device));
10399
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010400 if (!adev) {
10401 pthread_mutex_unlock(&adev_init_lock);
10402 return -ENOMEM;
10403 }
10404
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010405 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10406
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010407 // register audio ext hidl at the earliest
10408 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010409#ifdef DYNAMIC_LOG_ENABLED
10410 register_for_dynamic_logging("hal");
10411#endif
10412
Derek Chenf939fb72018-11-13 13:34:41 -080010413 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010414 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010415 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10416 maj_version = atoi(value);
10417
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010418 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010419 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010420 adev->device.common.module = (struct hw_module_t *)module;
10421 adev->device.common.close = adev_close;
10422
10423 adev->device.init_check = adev_init_check;
10424 adev->device.set_voice_volume = adev_set_voice_volume;
10425 adev->device.set_master_volume = adev_set_master_volume;
10426 adev->device.get_master_volume = adev_get_master_volume;
10427 adev->device.set_master_mute = adev_set_master_mute;
10428 adev->device.get_master_mute = adev_get_master_mute;
10429 adev->device.set_mode = adev_set_mode;
10430 adev->device.set_mic_mute = adev_set_mic_mute;
10431 adev->device.get_mic_mute = adev_get_mic_mute;
10432 adev->device.set_parameters = adev_set_parameters;
10433 adev->device.get_parameters = adev_get_parameters;
10434 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10435 adev->device.open_output_stream = adev_open_output_stream;
10436 adev->device.close_output_stream = adev_close_output_stream;
10437 adev->device.open_input_stream = adev_open_input_stream;
10438 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010439 adev->device.create_audio_patch = adev_create_audio_patch;
10440 adev->device.release_audio_patch = adev_release_audio_patch;
10441 adev->device.get_audio_port = adev_get_audio_port;
10442 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010443 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010444 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010445
10446 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010447 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010448 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010449 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010450 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010451 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010452 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010453 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010454 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010455 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010456 /* Init audio and voice feature */
10457 audio_extn_feature_init();
10458 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010459 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010460 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010461 list_init(&adev->active_inputs_list);
10462 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010463 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010464 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10465 audio_extn_utils_hash_eq);
10466 if (!adev->io_streams_map) {
10467 ALOGE("%s: Could not create io streams map", __func__);
10468 ret = -ENOMEM;
10469 goto adev_open_err;
10470 }
10471 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10472 audio_extn_utils_hash_eq);
10473 if (!adev->patch_map) {
10474 ALOGE("%s: Could not create audio patch map", __func__);
10475 ret = -ENOMEM;
10476 goto adev_open_err;
10477 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010478 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010479 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010480 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010481 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010482 adev->perf_lock_opts[0] = 0x101;
10483 adev->perf_lock_opts[1] = 0x20E;
10484 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010485 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010486 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010487 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010488 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010489
Zhou Song68ebc352019-12-05 17:11:15 +080010490 audio_extn_perf_lock_init();
10491
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010492 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010493 adev->platform = platform_init(adev);
10494 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010495 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010496 ret = -EINVAL;
10497 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010498 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010499
Aalique Grahame22e49102018-12-18 14:23:57 -080010500 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010501 if (audio_extn_qap_is_enabled()) {
10502 ret = audio_extn_qap_init(adev);
10503 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010504 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010505 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010506 }
10507 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10508 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10509 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010510
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010511 if (audio_extn_qaf_is_enabled()) {
10512 ret = audio_extn_qaf_init(adev);
10513 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010514 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010515 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010516 }
10517
10518 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10519 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10520 }
10521
Derek Chenae7b0342019-02-08 15:17:04 -080010522 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010523 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10524
Eric Laurentc4aef752013-09-12 17:45:53 -070010525 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10526 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10527 if (adev->visualizer_lib == NULL) {
10528 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10529 } else {
10530 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10531 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010532 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010533 "visualizer_hal_start_output");
10534 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010535 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010536 "visualizer_hal_stop_output");
10537 }
10538 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010539 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010540 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010541 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010542 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010543 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010544 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010545
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010546 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10547 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10548 if (adev->offload_effects_lib == NULL) {
10549 ALOGE("%s: DLOPEN failed for %s", __func__,
10550 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10551 } else {
10552 ALOGV("%s: DLOPEN successful for %s", __func__,
10553 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10554 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010555 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010556 "offload_effects_bundle_hal_start_output");
10557 adev->offload_effects_stop_output =
10558 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10559 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010560 adev->offload_effects_set_hpx_state =
10561 (int (*)(bool))dlsym(adev->offload_effects_lib,
10562 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010563 adev->offload_effects_get_parameters =
10564 (void (*)(struct str_parms *, struct str_parms *))
10565 dlsym(adev->offload_effects_lib,
10566 "offload_effects_bundle_get_parameters");
10567 adev->offload_effects_set_parameters =
10568 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10569 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010570 }
10571 }
10572
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010573 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10574 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10575 if (adev->adm_lib == NULL) {
10576 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10577 } else {
10578 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10579 adev->adm_init = (adm_init_t)
10580 dlsym(adev->adm_lib, "adm_init");
10581 adev->adm_deinit = (adm_deinit_t)
10582 dlsym(adev->adm_lib, "adm_deinit");
10583 adev->adm_register_input_stream = (adm_register_input_stream_t)
10584 dlsym(adev->adm_lib, "adm_register_input_stream");
10585 adev->adm_register_output_stream = (adm_register_output_stream_t)
10586 dlsym(adev->adm_lib, "adm_register_output_stream");
10587 adev->adm_deregister_stream = (adm_deregister_stream_t)
10588 dlsym(adev->adm_lib, "adm_deregister_stream");
10589 adev->adm_request_focus = (adm_request_focus_t)
10590 dlsym(adev->adm_lib, "adm_request_focus");
10591 adev->adm_abandon_focus = (adm_abandon_focus_t)
10592 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010593 adev->adm_set_config = (adm_set_config_t)
10594 dlsym(adev->adm_lib, "adm_set_config");
10595 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10596 dlsym(adev->adm_lib, "adm_request_focus_v2");
10597 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10598 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10599 adev->adm_on_routing_change = (adm_on_routing_change_t)
10600 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010601 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10602 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010603 }
10604 }
10605
Aalique Grahame22e49102018-12-18 14:23:57 -080010606 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010607 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010608 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010609 //initialize this to false for now,
10610 //this will be set to true through set param
10611 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010612
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010613 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010614 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010615
10616 if (k_enable_extended_precision)
10617 adev_verify_devices(adev);
10618
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010619 adev->dsp_bit_width_enforce_mode =
10620 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010621
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010622 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10623 &adev->streams_output_cfg_list,
10624 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010625
Kiran Kandi910e1862013-10-29 13:29:42 -070010626 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010627
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010628 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010629 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010630 trial = atoi(value);
10631 if (period_size_is_plausible_for_low_latency(trial)) {
10632 pcm_config_low_latency.period_size = trial;
10633 pcm_config_low_latency.start_threshold = trial / 4;
10634 pcm_config_low_latency.avail_min = trial / 4;
10635 configured_low_latency_capture_period_size = trial;
10636 }
10637 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010638 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10639 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010640 trial = atoi(value);
10641 if (period_size_is_plausible_for_low_latency(trial)) {
10642 configured_low_latency_capture_period_size = trial;
10643 }
10644 }
10645
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010646 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10647
Eric Laurent4b084132018-10-19 17:33:43 -070010648 adev->camera_orientation = CAMERA_DEFAULT;
10649
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010650 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010651 af_period_multiplier = atoi(value);
10652 if (af_period_multiplier < 0)
10653 af_period_multiplier = 2;
10654 else if (af_period_multiplier > 4)
10655 af_period_multiplier = 4;
10656
10657 ALOGV("new period_multiplier = %d", af_period_multiplier);
10658 }
10659
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010660 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010661
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010662 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010663 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010664 pthread_mutex_unlock(&adev_init_lock);
10665
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010666 if (adev->adm_init)
10667 adev->adm_data = adev->adm_init();
10668
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010669 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010670 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010671
10672 audio_extn_snd_mon_init();
10673 pthread_mutex_lock(&adev->lock);
10674 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10675 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010676 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10677 /*
10678 * if the battery state callback happens before charging can be queried,
10679 * it will be guarded with the adev->lock held in the cb function and so
10680 * the callback value will reflect the latest state
10681 */
10682 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010683 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010684 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010685 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010686 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010687 /* Allocate memory for Device config params */
10688 adev->device_cfg_params = (struct audio_device_config_param*)
10689 calloc(platform_get_max_codec_backend(),
10690 sizeof(struct audio_device_config_param));
10691 if (adev->device_cfg_params == NULL)
10692 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010693
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010694 /*
10695 * Check if new PSPD matrix mixer control is supported. If not
10696 * supported, then set flag so that old mixer ctrl is sent while
10697 * sending pspd coefficients on older kernel version. Query mixer
10698 * control for default pcm id and channel value one.
10699 */
10700 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10701 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10702
10703 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10704 if (!ctl) {
10705 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10706 __func__, mixer_ctl_name);
10707 adev->use_old_pspd_mix_ctrl = true;
10708 }
10709
Eric Laurent994a6932013-07-17 11:51:42 -070010710 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010711 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010712
10713adev_open_err:
10714 free_map(adev->patch_map);
10715 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010716 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010717 pthread_mutex_destroy(&adev->lock);
10718 free(adev);
10719 adev = NULL;
10720 *device = NULL;
10721 pthread_mutex_unlock(&adev_init_lock);
10722 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010723}
10724
10725static struct hw_module_methods_t hal_module_methods = {
10726 .open = adev_open,
10727};
10728
10729struct audio_module HAL_MODULE_INFO_SYM = {
10730 .common = {
10731 .tag = HARDWARE_MODULE_TAG,
10732 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10733 .hal_api_version = HARDWARE_HAL_API_VERSION,
10734 .id = AUDIO_HARDWARE_MODULE_ID,
10735 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010736 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010737 .methods = &hal_module_methods,
10738 },
10739};