blob: ef888672e8e272f5531a21ae418abce16ab9cc2e [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080081#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080082
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053083#ifdef DYNAMIC_LOG_ENABLED
84#include <log_xml_parser.h>
85#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
86#include <log_utils.h>
87#endif
88
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053090/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
91#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070093#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070094#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053095#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053096#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070097#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070098#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070099
Aalique Grahame22e49102018-12-18 14:23:57 -0800100#define RECORD_GAIN_MIN 0.0f
101#define RECORD_GAIN_MAX 1.0f
102#define RECORD_VOLUME_CTL_MAX 0x2000
103
104/* treat as unsigned Q1.13 */
105#define APP_TYPE_GAIN_DEFAULT 0x2000
106
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700107#define PROXY_OPEN_RETRY_COUNT 100
108#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800109
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800110#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
111 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
112 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
113#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
114 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800115
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700116#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700117#define DEFAULT_VOIP_BUF_DURATION_MS 20
118#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
119#define DEFAULT_VOIP_SAMP_RATE 48000
120
121#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
122
123struct pcm_config default_pcm_config_voip_copp = {
124 .channels = 1,
125 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
126 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
127 .period_count = 2,
128 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800129 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
130 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700131};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700132
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700133#define MIN_CHANNEL_COUNT 1
134#define DEFAULT_CHANNEL_COUNT 2
135#define MAX_HIFI_CHANNEL_COUNT 8
136
Aalique Grahame22e49102018-12-18 14:23:57 -0800137#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
138#define MAX_CHANNEL_COUNT 1
139#else
140#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
141#define XSTR(x) STR(x)
142#define STR(x) #x
143#endif
144
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700145static unsigned int configured_low_latency_capture_period_size =
146 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
147
Haynes Mathew George16081042017-05-31 17:16:49 -0700148#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
149#define MMAP_PERIOD_COUNT_MIN 32
150#define MMAP_PERIOD_COUNT_MAX 512
151#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
152
Aalique Grahame22e49102018-12-18 14:23:57 -0800153/* This constant enables extended precision handling.
154 * TODO The flag is off until more testing is done.
155 */
156static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700157extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800158
Eric Laurentb23d5282013-05-14 15:27:20 -0700159struct pcm_config pcm_config_deep_buffer = {
160 .channels = 2,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
163 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
166 .stop_threshold = INT_MAX,
167 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
168};
169
170struct pcm_config pcm_config_low_latency = {
171 .channels = 2,
172 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
173 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
174 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
175 .format = PCM_FORMAT_S16_LE,
176 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
177 .stop_threshold = INT_MAX,
178 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
179};
180
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800181struct pcm_config pcm_config_haptics_audio = {
182 .channels = 1,
183 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
184 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
185 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
187 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
188 .stop_threshold = INT_MAX,
189 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
190};
191
192struct pcm_config pcm_config_haptics = {
193 .channels = 1,
194 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
195 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
196 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
197 .format = PCM_FORMAT_S16_LE,
198 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
199 .stop_threshold = INT_MAX,
200 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
201};
202
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700203static int af_period_multiplier = 4;
204struct pcm_config pcm_config_rt = {
205 .channels = 2,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = ULL_PERIOD_SIZE, //1 ms
208 .period_count = 512, //=> buffer size is 512ms
209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = ULL_PERIOD_SIZE, //1 ms
215};
216
Eric Laurentb23d5282013-05-14 15:27:20 -0700217struct pcm_config pcm_config_hdmi_multi = {
218 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
219 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
220 .period_size = HDMI_MULTI_PERIOD_SIZE,
221 .period_count = HDMI_MULTI_PERIOD_COUNT,
222 .format = PCM_FORMAT_S16_LE,
223 .start_threshold = 0,
224 .stop_threshold = INT_MAX,
225 .avail_min = 0,
226};
227
Haynes Mathew George16081042017-05-31 17:16:49 -0700228struct pcm_config pcm_config_mmap_playback = {
229 .channels = 2,
230 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
231 .period_size = MMAP_PERIOD_SIZE,
232 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
233 .format = PCM_FORMAT_S16_LE,
234 .start_threshold = MMAP_PERIOD_SIZE*8,
235 .stop_threshold = INT32_MAX,
236 .silence_threshold = 0,
237 .silence_size = 0,
238 .avail_min = MMAP_PERIOD_SIZE, //1 ms
239};
240
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700241struct pcm_config pcm_config_hifi = {
242 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
243 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
244 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
245 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
246 .format = PCM_FORMAT_S24_3LE,
247 .start_threshold = 0,
248 .stop_threshold = INT_MAX,
249 .avail_min = 0,
250};
251
Eric Laurentb23d5282013-05-14 15:27:20 -0700252struct pcm_config pcm_config_audio_capture = {
253 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700254 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
255 .format = PCM_FORMAT_S16_LE,
256};
257
Haynes Mathew George16081042017-05-31 17:16:49 -0700258struct pcm_config pcm_config_mmap_capture = {
259 .channels = 2,
260 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
261 .period_size = MMAP_PERIOD_SIZE,
262 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
263 .format = PCM_FORMAT_S16_LE,
264 .start_threshold = 0,
265 .stop_threshold = INT_MAX,
266 .silence_threshold = 0,
267 .silence_size = 0,
268 .avail_min = MMAP_PERIOD_SIZE, //1 ms
269};
270
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700271#define AFE_PROXY_CHANNEL_COUNT 2
272#define AFE_PROXY_SAMPLING_RATE 48000
273
274#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
275#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
276
277struct pcm_config pcm_config_afe_proxy_playback = {
278 .channels = AFE_PROXY_CHANNEL_COUNT,
279 .rate = AFE_PROXY_SAMPLING_RATE,
280 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
281 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
282 .format = PCM_FORMAT_S16_LE,
283 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
284 .stop_threshold = INT_MAX,
285 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286};
287
288#define AFE_PROXY_RECORD_PERIOD_SIZE 768
289#define AFE_PROXY_RECORD_PERIOD_COUNT 4
290
Aalique Grahame22e49102018-12-18 14:23:57 -0800291struct pcm_config pcm_config_audio_capture_rt = {
292 .channels = 2,
293 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
294 .period_size = ULL_PERIOD_SIZE,
295 .period_count = 512,
296 .format = PCM_FORMAT_S16_LE,
297 .start_threshold = 0,
298 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
299 .silence_threshold = 0,
300 .silence_size = 0,
301 .avail_min = ULL_PERIOD_SIZE, //1 ms
302};
303
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700304struct pcm_config pcm_config_afe_proxy_record = {
305 .channels = AFE_PROXY_CHANNEL_COUNT,
306 .rate = AFE_PROXY_SAMPLING_RATE,
307 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
308 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
309 .format = PCM_FORMAT_S16_LE,
310 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
311 .stop_threshold = INT_MAX,
312 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
313};
314
Ashish Jainf1eaa582016-05-23 20:54:24 +0530315#define AUDIO_MAX_PCM_FORMATS 7
316
317const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
318 [AUDIO_FORMAT_DEFAULT] = 0,
319 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
320 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
321 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
322 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
323 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
324 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
325};
326
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800327const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700328 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
329 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800330 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800331 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700332 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
333 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700334 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700335 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700336 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
341 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700344 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
345 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700346 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800347 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700348
Eric Laurentb23d5282013-05-14 15:27:20 -0700349 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700350 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530351 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
352 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
353 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530354 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
355 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700356 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700357 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700358 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700359 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700360
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800361 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800362 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400363 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
364 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700365
Derek Chenf7092792017-05-23 12:23:53 -0400366 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700367 [USECASE_VOICE2_CALL] = "voice2-call",
368 [USECASE_VOLTE_CALL] = "volte-call",
369 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800370 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800371 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
372 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800373 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700374 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
375 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
376 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800377 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
378 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
379 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
380
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700381 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
382 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700383 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
384 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700385
386 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
387 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800388 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530389 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700390
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530391 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530392 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
393 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700394
395 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
396 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530397 /* For Interactive Audio Streams */
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
401 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
402 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
403 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700406
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800407 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
408
Derek Chenf6318be2017-06-12 17:16:24 -0400409 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
410
411 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
412 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
413 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
414 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800415 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700416 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530417 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700418};
419
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700420static const audio_usecase_t offload_usecases[] = {
421 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700422 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
426 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
427 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
428 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700430};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800431
Varun Balaraje49253e2017-07-06 19:48:56 +0530432static const audio_usecase_t interactive_usecases[] = {
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
437 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
438 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
441};
442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443#define STRING_TO_ENUM(string) { #string, string }
444
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800445struct string_to_enum {
446 const char *name;
447 uint32_t value;
448};
449
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700450static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700455 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800456 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700459 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
460 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
461 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
466 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
467 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800470};
471
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700472static const struct string_to_enum formats_name_to_enum_table[] = {
473 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
474 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
475 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700476 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
477 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
478 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700479 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800480 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
481 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700482 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800483};
484
485//list of all supported sample rates by HDMI specification.
486static const int out_hdmi_sample_rates[] = {
487 32000, 44100, 48000, 88200, 96000, 176400, 192000,
488};
489
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700490static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800491 STRING_TO_ENUM(32000),
492 STRING_TO_ENUM(44100),
493 STRING_TO_ENUM(48000),
494 STRING_TO_ENUM(88200),
495 STRING_TO_ENUM(96000),
496 STRING_TO_ENUM(176400),
497 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800498 STRING_TO_ENUM(352800),
499 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700500};
501
Carter Hsu2e429db2019-05-14 18:50:52 +0800502struct in_effect_list {
503 struct listnode list;
504 effect_handle_t handle;
505};
506
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700507static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700508static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700509static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700510//cache last MBDRC cal step level
511static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700512
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530513static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
514static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700515static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800516static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530517static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530518
Derek Chen6f293672019-04-01 01:40:24 -0700519static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
520static void in_snd_mon_cb(void * stream, struct str_parms * parms);
521static void out_snd_mon_cb(void * stream, struct str_parms * parms);
522
Zhou Song331c8e52019-08-26 14:16:12 +0800523static int configure_btsco_sample_rate(snd_device_t snd_device);
524
Vatsal Buchac09ae062018-11-14 13:25:08 +0530525#ifdef AUDIO_FEATURE_ENABLED_GCOV
526extern void __gcov_flush();
527static void enable_gcov()
528{
529 __gcov_flush();
530}
531#else
532static void enable_gcov()
533{
534}
535#endif
536
justinweng20fb6d82019-02-21 18:49:00 -0700537static int in_set_microphone_direction(const struct audio_stream_in *stream,
538 audio_microphone_direction_t dir);
539static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
540
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700541static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
542 int flags __unused)
543{
544 int dir = 0;
545 switch (uc_id) {
546 case USECASE_AUDIO_RECORD_LOW_LATENCY:
547 dir = 1;
548 case USECASE_AUDIO_PLAYBACK_ULL:
549 break;
550 default:
551 return false;
552 }
553
554 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
555 PCM_PLAYBACK : PCM_CAPTURE);
556 if (adev->adm_is_noirq_avail)
557 return adev->adm_is_noirq_avail(adev->adm_data,
558 adev->snd_card, dev_id, dir);
559 return false;
560}
561
562static void register_out_stream(struct stream_out *out)
563{
564 struct audio_device *adev = out->dev;
565 if (is_offload_usecase(out->usecase) ||
566 !adev->adm_register_output_stream)
567 return;
568
569 // register stream first for backward compatibility
570 adev->adm_register_output_stream(adev->adm_data,
571 out->handle,
572 out->flags);
573
574 if (!adev->adm_set_config)
575 return;
576
577 if (out->realtime)
578 adev->adm_set_config(adev->adm_data,
579 out->handle,
580 out->pcm, &out->config);
581}
582
583static void register_in_stream(struct stream_in *in)
584{
585 struct audio_device *adev = in->dev;
586 if (!adev->adm_register_input_stream)
587 return;
588
589 adev->adm_register_input_stream(adev->adm_data,
590 in->capture_handle,
591 in->flags);
592
593 if (!adev->adm_set_config)
594 return;
595
596 if (in->realtime)
597 adev->adm_set_config(adev->adm_data,
598 in->capture_handle,
599 in->pcm,
600 &in->config);
601}
602
603static void request_out_focus(struct stream_out *out, long ns)
604{
605 struct audio_device *adev = out->dev;
606
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700607 if (adev->adm_request_focus_v2)
608 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
609 else if (adev->adm_request_focus)
610 adev->adm_request_focus(adev->adm_data, out->handle);
611}
612
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700613static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700614{
615 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700616 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700617
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700618 if (adev->adm_request_focus_v2_1)
619 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
620 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
622 else if (adev->adm_request_focus)
623 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700624
625 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700626}
627
628static void release_out_focus(struct stream_out *out)
629{
630 struct audio_device *adev = out->dev;
631
632 if (adev->adm_abandon_focus)
633 adev->adm_abandon_focus(adev->adm_data, out->handle);
634}
635
636static void release_in_focus(struct stream_in *in)
637{
638 struct audio_device *adev = in->dev;
639 if (adev->adm_abandon_focus)
640 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
641}
642
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530643static int parse_snd_card_status(struct str_parms *parms, int *card,
644 card_status_t *status)
645{
646 char value[32]={0};
647 char state[32]={0};
648
649 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
650 if (ret < 0)
651 return -1;
652
653 // sscanf should be okay as value is of max length 32.
654 // same as sizeof state.
655 if (sscanf(value, "%d,%s", card, state) < 2)
656 return -1;
657
658 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
659 CARD_STATUS_OFFLINE;
660 return 0;
661}
662
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700663static inline void adjust_frames_for_device_delay(struct stream_out *out,
664 uint32_t *dsp_frames) {
665 // Adjustment accounts for A2dp encoder latency with offload usecases
666 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800667 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700668 unsigned long offset =
669 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
670 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
671 }
672}
673
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700674static inline bool free_entry(void *key __unused,
675 void *value, void *context __unused)
676{
677 free(value);
678 return true;
679}
680
681static inline void free_map(Hashmap *map)
682{
683 if (map) {
684 hashmapForEach(map, free_entry, (void *) NULL);
685 hashmapFree(map);
686 }
687}
688
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800689static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700690 audio_patch_handle_t patch_handle)
691{
692 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
693 return;
694
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700695 struct audio_patch_info *p_info =
696 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
697 if (p_info) {
698 ALOGV("%s: Remove patch %d", __func__, patch_handle);
699 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
700 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700701 free(p_info);
702 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700703}
704
705static inline int io_streams_map_insert(struct audio_device *adev,
706 struct audio_stream *stream,
707 audio_io_handle_t handle,
708 audio_patch_handle_t patch_handle)
709{
710 struct audio_stream_info *s_info =
711 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
712
713 if (s_info == NULL) {
714 ALOGE("%s: Could not allocate stream info", __func__);
715 return -ENOMEM;
716 }
717 s_info->stream = stream;
718 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700719
720 pthread_mutex_lock(&adev->lock);
721 struct audio_stream_info *stream_info =
722 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700723 if (stream_info != NULL)
724 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800725 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700726 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
727 return 0;
728}
729
730static inline void io_streams_map_remove(struct audio_device *adev,
731 audio_io_handle_t handle)
732{
733 pthread_mutex_lock(&adev->lock);
734 struct audio_stream_info *s_info =
735 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700736 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800737 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700738 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800739 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700740 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800741done:
742 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 return;
744}
745
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800746static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 audio_patch_handle_t handle)
748{
749 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700750 p_info = (struct audio_patch_info *)
751 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700752 return p_info;
753}
754
vivek mehtaa76401a2015-04-24 14:12:15 -0700755__attribute__ ((visibility ("default")))
756bool audio_hw_send_gain_dep_calibration(int level) {
757 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700758 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700759
760 pthread_mutex_lock(&adev_init_lock);
761
762 if (adev != NULL && adev->platform != NULL) {
763 pthread_mutex_lock(&adev->lock);
764 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700765
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530766 // cache level info for any of the use case which
767 // was not started.
768 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700769
vivek mehtaa76401a2015-04-24 14:12:15 -0700770 pthread_mutex_unlock(&adev->lock);
771 } else {
772 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
773 }
774
775 pthread_mutex_unlock(&adev_init_lock);
776
777 return ret_val;
778}
779
Ashish Jain5106d362016-05-11 19:23:33 +0530780static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
781{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800782 bool gapless_enabled = false;
783 const char *mixer_ctl_name = "Compress Gapless Playback";
784 struct mixer_ctl *ctl;
785
786 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700787 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530788
789 /*Disable gapless if its AV playback*/
790 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800791
792 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
793 if (!ctl) {
794 ALOGE("%s: Could not get ctl for mixer cmd - %s",
795 __func__, mixer_ctl_name);
796 return -EINVAL;
797 }
798
799 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
800 ALOGE("%s: Could not set gapless mode %d",
801 __func__, gapless_enabled);
802 return -EINVAL;
803 }
804 return 0;
805}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700806
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700807__attribute__ ((visibility ("default")))
808int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
809 int table_size) {
810 int ret_val = 0;
811 ALOGV("%s: enter ... ", __func__);
812
813 pthread_mutex_lock(&adev_init_lock);
814 if (adev == NULL) {
815 ALOGW("%s: adev is NULL .... ", __func__);
816 goto done;
817 }
818
819 pthread_mutex_lock(&adev->lock);
820 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
821 pthread_mutex_unlock(&adev->lock);
822done:
823 pthread_mutex_unlock(&adev_init_lock);
824 ALOGV("%s: exit ... ", __func__);
825 return ret_val;
826}
827
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800828bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800829{
830 bool ret = false;
831 ALOGV("%s: enter ...", __func__);
832
833 pthread_mutex_lock(&adev_init_lock);
834
835 if (adev != NULL && adev->platform != NULL) {
836 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800837 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800838 pthread_mutex_unlock(&adev->lock);
839 }
840
841 pthread_mutex_unlock(&adev_init_lock);
842
843 ALOGV("%s: exit with ret %d", __func__, ret);
844 return ret;
845}
Aalique Grahame22e49102018-12-18 14:23:57 -0800846
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700847static bool is_supported_format(audio_format_t format)
848{
Eric Laurent86e17132013-09-12 17:49:30 -0700849 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530850 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530851 format == AUDIO_FORMAT_AAC_LC ||
852 format == AUDIO_FORMAT_AAC_HE_V1 ||
853 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530854 format == AUDIO_FORMAT_AAC_ADTS_LC ||
855 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
856 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530857 format == AUDIO_FORMAT_AAC_LATM_LC ||
858 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
859 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530860 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
861 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530862 format == AUDIO_FORMAT_PCM_FLOAT ||
863 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700864 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530865 format == AUDIO_FORMAT_AC3 ||
866 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700867 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530868 format == AUDIO_FORMAT_DTS ||
869 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800870 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530871 format == AUDIO_FORMAT_ALAC ||
872 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530873 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530874 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800875 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530876 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700877 format == AUDIO_FORMAT_APTX ||
878 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800879 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700880
881 return false;
882}
883
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700884static inline bool is_mmap_usecase(audio_usecase_t uc_id)
885{
886 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800887 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700888 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
889}
890
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700891static inline bool is_valid_volume(float left, float right)
892{
893 return ((left >= 0.0f && right >= 0.0f) ? true : false);
894}
895
Avinash Vaish71a8b972014-07-24 15:36:33 +0530896static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
897 struct audio_usecase *uc_info)
898{
899 struct listnode *node;
900 struct audio_usecase *usecase;
901
902 if (uc_info == NULL)
903 return -EINVAL;
904
905 /* Re-route all voice usecases on the shared backend other than the
906 specified usecase to new snd devices */
907 list_for_each(node, &adev->usecase_list) {
908 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800909 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530910 enable_audio_route(adev, usecase);
911 }
912 return 0;
913}
914
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530915static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530916{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530917 ALOGV("%s", __func__);
918 audio_route_apply_and_update_path(adev->audio_route,
919 "asrc-mode");
920 adev->asrc_mode_enabled = true;
921}
922
923static void disable_asrc_mode(struct audio_device *adev)
924{
925 ALOGV("%s", __func__);
926 audio_route_reset_and_update_path(adev->audio_route,
927 "asrc-mode");
928 adev->asrc_mode_enabled = false;
929}
930
931/*
932 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
933 * 44.1 or Native DSD backends are enabled for any of current use case.
934 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
935 * - Disable current mix path use case(Headphone backend) and re-enable it with
936 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
937 * e.g. Naitve DSD or Headphone 44.1 -> + 48
938 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530939static void check_and_set_asrc_mode(struct audio_device *adev,
940 struct audio_usecase *uc_info,
941 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530942{
943 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530944 int i, num_new_devices = 0;
945 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
946 /*
947 *Split snd device for new combo use case
948 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
949 */
950 if (platform_split_snd_device(adev->platform,
951 snd_device,
952 &num_new_devices,
953 split_new_snd_devices) == 0) {
954 for (i = 0; i < num_new_devices; i++)
955 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
956 } else {
957 int new_backend_idx = platform_get_backend_index(snd_device);
958 if (((new_backend_idx == HEADPHONE_BACKEND) ||
959 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
960 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
961 !adev->asrc_mode_enabled) {
962 struct listnode *node = NULL;
963 struct audio_usecase *uc = NULL;
964 struct stream_out *curr_out = NULL;
965 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
966 int i, num_devices, ret = 0;
967 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530968
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530969 list_for_each(node, &adev->usecase_list) {
970 uc = node_to_item(node, struct audio_usecase, list);
971 curr_out = (struct stream_out*) uc->stream.out;
972 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
973 /*
974 *Split snd device for existing combo use case
975 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
976 */
977 ret = platform_split_snd_device(adev->platform,
978 uc->out_snd_device,
979 &num_devices,
980 split_snd_devices);
981 if (ret < 0 || num_devices == 0) {
982 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
983 split_snd_devices[0] = uc->out_snd_device;
984 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800985 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530986 for (i = 0; i < num_devices; i++) {
987 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
988 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
989 if((new_backend_idx == HEADPHONE_BACKEND) &&
990 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
991 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
992 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
993 __func__);
994 enable_asrc_mode(adev);
995 break;
996 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
997 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
998 (usecase_backend_idx == HEADPHONE_BACKEND)) {
999 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
1000 __func__);
1001 disable_audio_route(adev, uc);
1002 disable_snd_device(adev, uc->out_snd_device);
1003 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1004 if (new_backend_idx == DSD_NATIVE_BACKEND)
1005 audio_route_apply_and_update_path(adev->audio_route,
1006 "hph-true-highquality-mode");
1007 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1008 (curr_out->bit_width >= 24))
1009 audio_route_apply_and_update_path(adev->audio_route,
1010 "hph-highquality-mode");
1011 enable_asrc_mode(adev);
1012 enable_snd_device(adev, uc->out_snd_device);
1013 enable_audio_route(adev, uc);
1014 break;
1015 }
1016 }
1017 // reset split devices count
1018 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001019 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301020 if (adev->asrc_mode_enabled)
1021 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301022 }
1023 }
1024 }
1025}
1026
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001027static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1028 struct audio_effect_config effect_config,
1029 unsigned int param_value)
1030{
1031 char mixer_ctl_name[] = "Audio Effect";
1032 struct mixer_ctl *ctl;
1033 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001034 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001035
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001036 if (in == NULL) {
1037 ALOGE("%s: active input stream is NULL", __func__);
1038 return -EINVAL;
1039 }
1040
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001041 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1042 if (!ctl) {
1043 ALOGE("%s: Could not get mixer ctl - %s",
1044 __func__, mixer_ctl_name);
1045 return -EINVAL;
1046 }
1047
1048 set_values[0] = 1; //0:Rx 1:Tx
1049 set_values[1] = in->app_type_cfg.app_type;
1050 set_values[2] = (long)effect_config.module_id;
1051 set_values[3] = (long)effect_config.instance_id;
1052 set_values[4] = (long)effect_config.param_id;
1053 set_values[5] = param_value;
1054
1055 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1056
1057 return 0;
1058
1059}
1060
1061static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1062 int effect_type, unsigned int *param_value)
1063{
1064 int ret = 0;
1065 struct audio_effect_config other_effect_config;
1066 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001067 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001068
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001069 if (in == NULL) {
1070 ALOGE("%s: active input stream is NULL", __func__);
1071 return -EINVAL;
1072 }
1073
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001074 usecase = get_usecase_from_list(adev, in->usecase);
1075 if (!usecase)
1076 return -EINVAL;
1077
1078 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1079 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1080 if (ret < 0) {
1081 ALOGE("%s Failed to get effect params %d", __func__, ret);
1082 return ret;
1083 }
1084
1085 if (module_id == other_effect_config.module_id) {
1086 //Same module id for AEC/NS. Values need to be combined
1087 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1088 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1089 *param_value |= other_effect_config.param_value;
1090 }
1091 }
1092
1093 return ret;
1094}
1095
1096static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301097{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001098 struct audio_effect_config effect_config;
1099 struct audio_usecase *usecase = NULL;
1100 int ret = 0;
1101 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001102 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001103
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001104 if(!voice_extn_is_dynamic_ecns_enabled())
1105 return ENOSYS;
1106
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001107 if (!in) {
1108 ALOGE("%s: Invalid input stream", __func__);
1109 return -EINVAL;
1110 }
1111
1112 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1113
1114 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001115 if (usecase == NULL) {
1116 ALOGE("%s: Could not find the usecase (%d) in the list",
1117 __func__, in->usecase);
1118 return -EINVAL;
1119 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001120
1121 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1122 if (ret < 0) {
1123 ALOGE("%s Failed to get module id %d", __func__, ret);
1124 return ret;
1125 }
1126 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1127 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1128
1129 if(enable)
1130 param_value = effect_config.param_value;
1131
1132 /*Special handling for AEC & NS effects Param values need to be
1133 updated if module ids are same*/
1134
1135 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1136 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1137 if (ret < 0)
1138 return ret;
1139 }
1140
1141 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1142
1143 return ret;
1144}
1145
1146static void check_and_enable_effect(struct audio_device *adev)
1147{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001148 if(!voice_extn_is_dynamic_ecns_enabled())
1149 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001150
Eric Laurent637e2d42018-11-15 12:24:31 -08001151 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001152
Eric Laurent637e2d42018-11-15 12:24:31 -08001153 if (in != NULL && !in->standby) {
1154 if (in->enable_aec)
1155 enable_disable_effect(adev, EFFECT_AEC, true);
1156
1157 if (in->enable_ns &&
1158 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1159 enable_disable_effect(adev, EFFECT_NS, true);
1160 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001161 }
1162}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001163
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001164int pcm_ioctl(struct pcm *pcm, int request, ...)
1165{
1166 va_list ap;
1167 void * arg;
1168 int pcm_fd = *(int*)pcm;
1169
1170 va_start(ap, request);
1171 arg = va_arg(ap, void *);
1172 va_end(ap);
1173
1174 return ioctl(pcm_fd, request, arg);
1175}
1176
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001177int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001178 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001179{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001180 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001181 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301182 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301183 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001184 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301185 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001186
1187 if (usecase == NULL)
1188 return -EINVAL;
1189
1190 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1191
Carter Hsu2e429db2019-05-14 18:50:52 +08001192 if (usecase->type == PCM_CAPTURE) {
1193 struct stream_in *in = usecase->stream.in;
1194 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001195 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001196
1197 if (in) {
1198 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001199 list_init(&out_devices);
1200 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001201 struct listnode *node;
1202 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1203 USECASE_AUDIO_PLAYBACK_VOIP);
1204 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001205 assign_devices(&out_devices,
1206 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001207 } else if (adev->primary_output &&
1208 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001209 assign_devices(&out_devices,
1210 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001211 } else {
1212 list_for_each(node, &adev->usecase_list) {
1213 uinfo = node_to_item(node, struct audio_usecase, list);
1214 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001215 assign_devices(&out_devices,
1216 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001217 break;
1218 }
1219 }
1220 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001221
1222 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001223 in->ec_opened = true;
1224 }
1225 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001226 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1227 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1228 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001229 snd_device = usecase->in_snd_device;
1230 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001231 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001232 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001233
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001234#ifdef DS1_DOLBY_DAP_ENABLED
1235 audio_extn_dolby_set_dmid(adev);
1236 audio_extn_dolby_set_endpoint(adev);
1237#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001238 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001239 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301240 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001241 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001242 if (audio_extn_is_maxx_audio_enabled())
1243 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301244 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301245 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1246 out = usecase->stream.out;
1247 if (out && out->compr)
1248 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1249 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301250
1251 if (usecase->type == PCM_CAPTURE) {
1252 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001253 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301254 ALOGD("%s: set custom mtmx params v1", __func__);
1255 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1256 }
1257 } else {
1258 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1259 }
Manish Dewangan58229382017-02-02 15:48:41 +05301260
Andy Hung756ecc12018-10-19 17:47:12 -07001261 // we shouldn't truncate mixer_path
1262 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1263 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1264 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001265 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001266 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301267 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1268 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1269 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1270 if (parms) {
1271 audio_extn_fm_set_parameters(adev, parms);
1272 str_parms_destroy(parms);
1273 }
1274 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275 ALOGV("%s: exit", __func__);
1276 return 0;
1277}
1278
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001279int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001280 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001282 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001283 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301284 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001285
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301286 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001287 return -EINVAL;
1288
1289 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301290 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001291 snd_device = usecase->in_snd_device;
1292 else
1293 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001294 // we shouldn't truncate mixer_path
1295 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1296 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1297 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001298 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001299 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001300 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001301 if (usecase->type == PCM_CAPTURE) {
1302 struct stream_in *in = usecase->stream.in;
1303 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001304 struct listnode out_devices;
1305 list_init(&out_devices);
1306 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001307 in->ec_opened = false;
1308 }
1309 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001310 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301311 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301312
1313 if (usecase->type == PCM_CAPTURE) {
1314 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001315 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301316 ALOGD("%s: reset custom mtmx params v1", __func__);
1317 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1318 }
1319 } else {
1320 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1321 }
1322
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001323 if ((usecase->type == PCM_PLAYBACK) &&
1324 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301325 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301326
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001327 ALOGV("%s: exit", __func__);
1328 return 0;
1329}
1330
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001331int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001332 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001333{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301334 int i, num_devices = 0;
1335 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001336 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1337
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001338 if (snd_device < SND_DEVICE_MIN ||
1339 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001340 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001341 return -EINVAL;
1342 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001343
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001344 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001345 ALOGE("%s: Invalid sound device returned", __func__);
1346 return -EINVAL;
1347 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001348
1349 adev->snd_dev_ref_cnt[snd_device]++;
1350
1351 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1352 (platform_split_snd_device(adev->platform,
1353 snd_device,
1354 &num_devices,
1355 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001356 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001357 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001358 return 0;
1359 }
1360
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001361 if (audio_extn_spkr_prot_is_enabled())
1362 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001363
Aalique Grahame22e49102018-12-18 14:23:57 -08001364 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1365
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001366 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1367 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001368 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1369 goto err;
1370 }
1371 audio_extn_dev_arbi_acquire(snd_device);
1372 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001373 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001374 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001375 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001376 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001377 } else if (platform_split_snd_device(adev->platform,
1378 snd_device,
1379 &num_devices,
1380 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301381 for (i = 0; i < num_devices; i++) {
1382 enable_snd_device(adev, new_snd_devices[i]);
1383 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001384 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001385 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001386 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301387
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301388
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001389 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1390 (audio_extn_a2dp_start_playback() < 0)) {
1391 ALOGE(" fail to configure A2dp Source control path ");
1392 goto err;
1393 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001394
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001395 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1396 (audio_extn_a2dp_start_capture() < 0)) {
1397 ALOGE(" fail to configure A2dp Sink control path ");
1398 goto err;
1399 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301400
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001401 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1402 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1403 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1404 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1405 ALOGE(" fail to configure sco control path ");
1406 goto err;
1407 }
Zhou Song12c29502019-03-16 10:37:18 +08001408 }
1409
Zhou Song331c8e52019-08-26 14:16:12 +08001410 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001411 /* due to the possibility of calibration overwrite between listen
1412 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001413 audio_extn_sound_trigger_update_device_status(snd_device,
1414 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301415 audio_extn_listen_update_device_status(snd_device,
1416 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001417 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001418 audio_extn_sound_trigger_update_device_status(snd_device,
1419 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301420 audio_extn_listen_update_device_status(snd_device,
1421 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001422 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001423 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001424 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001425 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301426
1427 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1428 !adev->native_playback_enabled &&
1429 audio_is_true_native_stream_active(adev)) {
1430 ALOGD("%s: %d: napb: enabling native mode in hardware",
1431 __func__, __LINE__);
1432 audio_route_apply_and_update_path(adev->audio_route,
1433 "true-native-mode");
1434 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301435 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301436 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1437 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001438 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001439 ALOGD("%s: init ec ref loopback", __func__);
1440 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1441 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001444err:
1445 adev->snd_dev_ref_cnt[snd_device]--;
1446 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001447}
1448
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001449int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001450 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301452 int i, num_devices = 0;
1453 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001454 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1455
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001456 if (snd_device < SND_DEVICE_MIN ||
1457 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001458 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001459 return -EINVAL;
1460 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001461
1462 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1463 ALOGE("%s: Invalid sound device returned", __func__);
1464 return -EINVAL;
1465 }
1466
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1468 ALOGE("%s: device ref cnt is already 0", __func__);
1469 return -EINVAL;
1470 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001471
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001472 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001473
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001474
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001476 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301477
Aalique Grahame22e49102018-12-18 14:23:57 -08001478 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1479
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001480 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1481 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001482 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001483
1484 // when speaker device is disabled, reset swap.
1485 // will be renabled on usecase start
1486 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001487 } else if (platform_split_snd_device(adev->platform,
1488 snd_device,
1489 &num_devices,
1490 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301491 for (i = 0; i < num_devices; i++) {
1492 disable_snd_device(adev, new_snd_devices[i]);
1493 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001494 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001495 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001496 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001497 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001498
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001499 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301500 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001501 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001502 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001503 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001504 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301505 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001506 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301507 adev->native_playback_enabled) {
1508 ALOGD("%s: %d: napb: disabling native mode in hardware",
1509 __func__, __LINE__);
1510 audio_route_reset_and_update_path(adev->audio_route,
1511 "true-native-mode");
1512 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001513 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301514 adev->asrc_mode_enabled) {
1515 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301516 disable_asrc_mode(adev);
1517 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001518 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301519 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001520 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001521 ALOGD("%s: deinit ec ref loopback", __func__);
1522 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1523 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001524
1525 audio_extn_utils_release_snd_device(snd_device);
1526 } else {
1527 if (platform_split_snd_device(adev->platform,
1528 snd_device,
1529 &num_devices,
1530 new_snd_devices) == 0) {
1531 for (i = 0; i < num_devices; i++) {
1532 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1533 }
1534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001536
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537 return 0;
1538}
1539
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001540/*
1541 legend:
1542 uc - existing usecase
1543 new_uc - new usecase
1544 d1, d11, d2 - SND_DEVICE enums
1545 a1, a2 - corresponding ANDROID device enums
1546 B1, B2 - backend strings
1547
1548case 1
1549 uc->dev d1 (a1) B1
1550 new_uc->dev d1 (a1), d2 (a2) B1, B2
1551
1552 resolution: disable and enable uc->dev on d1
1553
1554case 2
1555 uc->dev d1 (a1) B1
1556 new_uc->dev d11 (a1) B1
1557
1558 resolution: need to switch uc since d1 and d11 are related
1559 (e.g. speaker and voice-speaker)
1560 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1561
1562case 3
1563 uc->dev d1 (a1) B1
1564 new_uc->dev d2 (a2) B2
1565
1566 resolution: no need to switch uc
1567
1568case 4
1569 uc->dev d1 (a1) B1
1570 new_uc->dev d2 (a2) B1
1571
1572 resolution: disable enable uc-dev on d2 since backends match
1573 we cannot enable two streams on two different devices if they
1574 share the same backend. e.g. if offload is on speaker device using
1575 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1576 using the same backend, offload must also be switched to voice-handset.
1577
1578case 5
1579 uc->dev d1 (a1) B1
1580 new_uc->dev d1 (a1), d2 (a2) B1
1581
1582 resolution: disable enable uc-dev on d2 since backends match
1583 we cannot enable two streams on two different devices if they
1584 share the same backend.
1585
1586case 6
1587 uc->dev d1 (a1) B1
1588 new_uc->dev d2 (a1) B2
1589
1590 resolution: no need to switch
1591
1592case 7
1593 uc->dev d1 (a1), d2 (a2) B1, B2
1594 new_uc->dev d1 (a1) B1
1595
1596 resolution: no need to switch
1597
Zhou Song4ba65882018-07-09 14:48:07 +08001598case 8
1599 uc->dev d1 (a1) B1
1600 new_uc->dev d11 (a1), d2 (a2) B1, B2
1601 resolution: compared to case 1, for this case, d1 and d11 are related
1602 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001603*/
1604static snd_device_t derive_playback_snd_device(void * platform,
1605 struct audio_usecase *uc,
1606 struct audio_usecase *new_uc,
1607 snd_device_t new_snd_device)
1608{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001609 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001610
1611 snd_device_t d1 = uc->out_snd_device;
1612 snd_device_t d2 = new_snd_device;
1613
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001614 list_init(&a1);
1615 list_init(&a2);
1616
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301617 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301618 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001619 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1620 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301621 break;
1622 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001623 assign_devices(&a1, &uc->stream.out->device_list);
1624 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301625 break;
1626 }
1627
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001628 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001629 if (!compare_devices(&a1, &a2) &&
1630 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001631 snd_device_t d3[2];
1632 int num_devices = 0;
1633 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001634 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001635 &num_devices,
1636 d3);
1637 if (ret < 0) {
1638 if (ret != -ENOSYS) {
1639 ALOGW("%s failed to split snd_device %d",
1640 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001641 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001642 }
1643 goto end;
1644 }
1645
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001646 if (platform_check_backends_match(d3[0], d3[1])) {
1647 return d2; // case 5
1648 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001649 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301650 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001651 // check if d1 is related to any of d3's
1652 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001653 return d1; // case 1
1654 else
1655 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001656 }
1657 } else {
1658 if (platform_check_backends_match(d1, d2)) {
1659 return d2; // case 2, 4
1660 } else {
1661 return d1; // case 6, 3
1662 }
1663 }
1664
1665end:
1666 return d2; // return whatever was calculated before.
1667}
1668
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001669static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301670 struct audio_usecase *uc_info,
1671 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001672{
1673 struct listnode *node;
1674 struct audio_usecase *usecase;
1675 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301676 snd_device_t uc_derive_snd_device;
1677 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001678 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1679 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001680 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301681 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001682 /*
1683 * This function is to make sure that all the usecases that are active on
1684 * the hardware codec backend are always routed to any one device that is
1685 * handled by the hardware codec.
1686 * For example, if low-latency and deep-buffer usecases are currently active
1687 * on speaker and out_set_parameters(headset) is received on low-latency
1688 * output, then we have to make sure deep-buffer is also switched to headset,
1689 * because of the limitation that both the devices cannot be enabled
1690 * at the same time as they share the same backend.
1691 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001692 /*
1693 * This call is to check if we need to force routing for a particular stream
1694 * If there is a backend configuration change for the device when a
1695 * new stream starts, then ADM needs to be closed and re-opened with the new
1696 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001697 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001698 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001699 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1700 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301701 /* For a2dp device reconfigure all active sessions
1702 * with new AFE encoder format based on a2dp state
1703 */
1704 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1705 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1706 audio_extn_a2dp_is_force_device_switch()) {
1707 force_routing = true;
1708 force_restart_session = true;
1709 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301710 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1711
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001713 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001714 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001715 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1716 switch_device[i] = false;
1717
1718 list_for_each(node, &adev->usecase_list) {
1719 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001720
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301721 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1722 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301723 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301724 platform_get_snd_device_name(usecase->out_snd_device),
1725 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301726 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1727 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301728 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1729 usecase, uc_info, snd_device);
1730 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001731 (is_codec_backend_out_device_type(&usecase->device_list) ||
1732 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1733 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1734 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1735 is_a2dp_out_device_type(&usecase->device_list) ||
1736 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301737 ((force_restart_session) ||
1738 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301739 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1740 __func__, use_case_table[usecase->id],
1741 platform_get_snd_device_name(usecase->out_snd_device));
1742 disable_audio_route(adev, usecase);
1743 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301744 /* Enable existing usecase on derived playback device */
1745 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301746 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301747 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001748 }
1749 }
1750
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301751 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1752 num_uc_to_switch);
1753
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001754 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001755 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001756
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301757 /* Make sure the previous devices to be disabled first and then enable the
1758 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001759 list_for_each(node, &adev->usecase_list) {
1760 usecase = node_to_item(node, struct audio_usecase, list);
1761 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001762 /* Check if output sound device to be switched can be split and if any
1763 of the split devices match with derived sound device */
1764 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1765 &num_devices, split_snd_devices) == 0) {
1766 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1767 for (i = 0; i < num_devices; i++) {
1768 /* Disable devices that do not match with derived sound device */
1769 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1770 disable_snd_device(adev, split_snd_devices[i]);
1771 }
1772 } else {
1773 disable_snd_device(adev, usecase->out_snd_device);
1774 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001775 }
1776 }
1777
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001778 list_for_each(node, &adev->usecase_list) {
1779 usecase = node_to_item(node, struct audio_usecase, list);
1780 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001781 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1782 &num_devices, split_snd_devices) == 0) {
1783 /* Enable derived sound device only if it does not match with
1784 one of the split sound devices. This is because the matching
1785 sound device was not disabled */
1786 bool should_enable = true;
1787 for (i = 0; i < num_devices; i++) {
1788 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1789 should_enable = false;
1790 break;
1791 }
1792 }
1793 if (should_enable)
1794 enable_snd_device(adev, derive_snd_device[usecase->id]);
1795 } else {
1796 enable_snd_device(adev, derive_snd_device[usecase->id]);
1797 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001798 }
1799 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001800
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001801 /* Re-route all the usecases on the shared backend other than the
1802 specified usecase to new snd devices */
1803 list_for_each(node, &adev->usecase_list) {
1804 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301805 /* Update the out_snd_device only before enabling the audio route */
1806 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301807 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301808 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301809 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301810 use_case_table[usecase->id],
1811 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001812 /* Update voc calibration before enabling VoIP route */
1813 if (usecase->type == VOIP_CALL)
1814 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001815 usecase->out_snd_device,
1816 platform_get_input_snd_device(
1817 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301818 &uc_info->device_list,
1819 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301820 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301821 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001822 out_set_voip_volume(&usecase->stream.out->stream,
1823 usecase->stream.out->volume_l,
1824 usecase->stream.out->volume_r);
1825 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301826 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001827 }
1828 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001829 }
1830}
1831
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301832static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001833 struct audio_usecase *uc_info,
1834 snd_device_t snd_device)
1835{
1836 struct listnode *node;
1837 struct audio_usecase *usecase;
1838 bool switch_device[AUDIO_USECASE_MAX];
1839 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001840 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001841 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001842
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301843 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1844 snd_device);
1845 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301846
1847 /*
1848 * Make sure out devices is checked against out codec backend device and
1849 * also in devices against in codec backend. Checking out device against in
1850 * codec backend or vice versa causes issues.
1851 */
1852 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001853 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001854 /*
1855 * This function is to make sure that all the active capture usecases
1856 * are always routed to the same input sound device.
1857 * For example, if audio-record and voice-call usecases are currently
1858 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1859 * is received for voice call then we have to make sure that audio-record
1860 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1861 * because of the limitation that two devices cannot be enabled
1862 * at the same time if they share the same backend.
1863 */
1864 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1865 switch_device[i] = false;
1866
1867 list_for_each(node, &adev->usecase_list) {
1868 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301869 /*
1870 * TODO: Enhance below condition to handle BT sco/USB multi recording
1871 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301872
1873 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1874 (usecase->in_snd_device != snd_device || force_routing));
1875 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1876 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1877 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001878 ((backend_check_cond &&
1879 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001880 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001881 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001882 is_single_device_type_equal(&usecase->device_list,
1883 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001884 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001885 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001886 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301887 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001888 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001889 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001890 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001891 switch_device[usecase->id] = true;
1892 num_uc_to_switch++;
1893 }
1894 }
1895
1896 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001897 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001898
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301899 /* Make sure the previous devices to be disabled first and then enable the
1900 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001901 list_for_each(node, &adev->usecase_list) {
1902 usecase = node_to_item(node, struct audio_usecase, list);
1903 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001904 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001905 }
1906 }
1907
1908 list_for_each(node, &adev->usecase_list) {
1909 usecase = node_to_item(node, struct audio_usecase, list);
1910 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001911 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001912 }
1913 }
1914
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001915 /* Re-route all the usecases on the shared backend other than the
1916 specified usecase to new snd devices */
1917 list_for_each(node, &adev->usecase_list) {
1918 usecase = node_to_item(node, struct audio_usecase, list);
1919 /* Update the in_snd_device only before enabling the audio route */
1920 if (switch_device[usecase->id] ) {
1921 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001922 if (usecase->type != VOICE_CALL) {
1923 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301924 if (usecase->type == VOIP_CALL) {
1925 snd_device_t voip_snd_device;
1926 voip_snd_device = platform_get_output_snd_device(adev->platform,
1927 uc_info->stream.out,
1928 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08001929 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301930 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08001931 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05301932 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05301933 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001934 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001935 }
1936 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001937 }
1938}
1939
Mingming Yin3a941d42016-02-17 18:08:05 -08001940static void reset_hdmi_sink_caps(struct stream_out *out) {
1941 int i = 0;
1942
1943 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1944 out->supported_channel_masks[i] = 0;
1945 }
1946 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1947 out->supported_formats[i] = 0;
1948 }
1949 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1950 out->supported_sample_rates[i] = 0;
1951 }
1952}
1953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001955static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956{
Mingming Yin3a941d42016-02-17 18:08:05 -08001957 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001958 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
1959 out->extconn.cs.controller,
1960 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961
Mingming Yin3a941d42016-02-17 18:08:05 -08001962 reset_hdmi_sink_caps(out);
1963
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001964 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08001965 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001966 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08001967 out->extconn.cs.stream);
1968 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001969 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001970 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001971 }
1972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001975 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001976 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001977 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1978 case 6:
1979 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1980 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1981 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1982 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1983 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1984 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001985 break;
1986 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001987 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001988 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 break;
1990 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001991
1992 // check channel format caps
1993 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001994 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
1995 out->extconn.cs.controller,
1996 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08001997 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1998 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1999 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2000 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2001 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2002 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2003 }
2004
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002005 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2006 out->extconn.cs.controller,
2007 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002008 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2009 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2010 }
2011
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002012 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2013 out->extconn.cs.controller,
2014 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002015 ALOGV(":%s HDMI supports DTS format", __func__);
2016 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2017 }
2018
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002019 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2020 out->extconn.cs.controller,
2021 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002022 ALOGV(":%s HDMI supports DTS HD format", __func__);
2023 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2024 }
2025
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002026 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2027 out->extconn.cs.controller,
2028 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002029 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2030 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2031 }
2032
Mingming Yin3a941d42016-02-17 18:08:05 -08002033
2034 // check sample rate caps
2035 i = 0;
2036 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002037 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2038 out->extconn.cs.controller,
2039 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002040 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2041 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2042 }
2043 }
2044
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002045 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046}
2047
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002048static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2049 uint32_t *supported_sample_rates __unused,
2050 uint32_t max_rates __unused)
2051{
2052 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2053 supported_sample_rates,
2054 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302055 ssize_t i = 0;
2056
2057 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002058 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2059 supported_sample_rates[i]);
2060 }
2061 return count;
2062}
2063
2064static inline int read_usb_sup_channel_masks(bool is_playback,
2065 audio_channel_mask_t *supported_channel_masks,
2066 uint32_t max_masks)
2067{
2068 int channels = audio_extn_usb_get_max_channels(is_playback);
2069 int channel_count;
2070 uint32_t num_masks = 0;
2071 if (channels > MAX_HIFI_CHANNEL_COUNT)
2072 channels = MAX_HIFI_CHANNEL_COUNT;
2073
2074 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002075 // start from 2 channels as framework currently doesn't support mono.
2076 if (channels >= FCC_2) {
2077 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2078 }
2079 for (channel_count = FCC_2;
2080 channel_count <= channels && num_masks < max_masks;
2081 ++channel_count) {
2082 supported_channel_masks[num_masks++] =
2083 audio_channel_mask_for_index_assignment_from_count(channel_count);
2084 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002085 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002086 // For capture we report all supported channel masks from 1 channel up.
2087 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002088 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2089 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002090 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2091 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2092 if (channel_count <= FCC_2) {
2093 mask = audio_channel_in_mask_from_count(channel_count);
2094 supported_channel_masks[num_masks++] = mask;
2095 }
2096 const audio_channel_mask_t index_mask =
2097 audio_channel_mask_for_index_assignment_from_count(channel_count);
2098 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2099 supported_channel_masks[num_masks++] = index_mask;
2100 }
2101 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002102 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302103
vincenttewf51c94e2019-05-07 10:28:53 +08002104 for (size_t i = 0; i < num_masks; ++i) {
2105 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2106 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302107 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002108 return num_masks;
2109}
2110
2111static inline int read_usb_sup_formats(bool is_playback __unused,
2112 audio_format_t *supported_formats,
2113 uint32_t max_formats __unused)
2114{
2115 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2116 switch (bitwidth) {
2117 case 24:
2118 // XXX : usb.c returns 24 for s24 and s24_le?
2119 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2120 break;
2121 case 32:
2122 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2123 break;
2124 case 16:
2125 default :
2126 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2127 break;
2128 }
2129 ALOGV("%s: %s supported format %d", __func__,
2130 is_playback ? "P" : "C", bitwidth);
2131 return 1;
2132}
2133
2134static inline int read_usb_sup_params_and_compare(bool is_playback,
2135 audio_format_t *format,
2136 audio_format_t *supported_formats,
2137 uint32_t max_formats,
2138 audio_channel_mask_t *mask,
2139 audio_channel_mask_t *supported_channel_masks,
2140 uint32_t max_masks,
2141 uint32_t *rate,
2142 uint32_t *supported_sample_rates,
2143 uint32_t max_rates) {
2144 int ret = 0;
2145 int num_formats;
2146 int num_masks;
2147 int num_rates;
2148 int i;
2149
2150 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2151 max_formats);
2152 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2153 max_masks);
2154
2155 num_rates = read_usb_sup_sample_rates(is_playback,
2156 supported_sample_rates, max_rates);
2157
2158#define LUT(table, len, what, dflt) \
2159 for (i=0; i<len && (table[i] != what); i++); \
2160 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2161
2162 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2163 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2164 LUT(supported_sample_rates, num_rates, *rate, 0);
2165
2166#undef LUT
2167 return ret < 0 ? -EINVAL : 0; // HACK TBD
2168}
2169
Alexy Josephb1379942016-01-29 15:49:38 -08002170audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002171 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002172{
2173 struct audio_usecase *usecase;
2174 struct listnode *node;
2175
2176 list_for_each(node, &adev->usecase_list) {
2177 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002178 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002179 ALOGV("%s: usecase id %d", __func__, usecase->id);
2180 return usecase->id;
2181 }
2182 }
2183 return USECASE_INVALID;
2184}
2185
Alexy Josephb1379942016-01-29 15:49:38 -08002186struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002187 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002188{
2189 struct audio_usecase *usecase;
2190 struct listnode *node;
2191
2192 list_for_each(node, &adev->usecase_list) {
2193 usecase = node_to_item(node, struct audio_usecase, list);
2194 if (usecase->id == uc_id)
2195 return usecase;
2196 }
2197 return NULL;
2198}
2199
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302200/*
2201 * is a true native playback active
2202 */
2203bool audio_is_true_native_stream_active(struct audio_device *adev)
2204{
2205 bool active = false;
2206 int i = 0;
2207 struct listnode *node;
2208
2209 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2210 ALOGV("%s:napb: not in true mode or non hdphones device",
2211 __func__);
2212 active = false;
2213 goto exit;
2214 }
2215
2216 list_for_each(node, &adev->usecase_list) {
2217 struct audio_usecase *uc;
2218 uc = node_to_item(node, struct audio_usecase, list);
2219 struct stream_out *curr_out =
2220 (struct stream_out*) uc->stream.out;
2221
2222 if (curr_out && PCM_PLAYBACK == uc->type) {
2223 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2224 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2225 uc->id, curr_out->sample_rate,
2226 curr_out->bit_width,
2227 platform_get_snd_device_name(uc->out_snd_device));
2228
2229 if (is_offload_usecase(uc->id) &&
2230 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2231 active = true;
2232 ALOGD("%s:napb:native stream detected", __func__);
2233 }
2234 }
2235 }
2236exit:
2237 return active;
2238}
2239
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002240uint32_t adev_get_dsp_bit_width_enforce_mode()
2241{
2242 if (adev == NULL) {
2243 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2244 return 0;
2245 }
2246 return adev->dsp_bit_width_enforce_mode;
2247}
2248
2249static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2250{
2251 char value[PROPERTY_VALUE_MAX];
2252 int trial;
2253 uint32_t dsp_bit_width_enforce_mode = 0;
2254
2255 if (!mixer) {
2256 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2257 __func__);
2258 return 0;
2259 }
2260
2261 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2262 value, NULL) > 0) {
2263 trial = atoi(value);
2264 switch (trial) {
2265 case 16:
2266 dsp_bit_width_enforce_mode = 16;
2267 break;
2268 case 24:
2269 dsp_bit_width_enforce_mode = 24;
2270 break;
2271 case 32:
2272 dsp_bit_width_enforce_mode = 32;
2273 break;
2274 default:
2275 dsp_bit_width_enforce_mode = 0;
2276 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2277 break;
2278 }
2279 }
2280
2281 return dsp_bit_width_enforce_mode;
2282}
2283
2284static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2285 uint32_t enforce_mode,
2286 bool enable)
2287{
2288 struct mixer_ctl *ctl = NULL;
2289 const char *mixer_ctl_name = "ASM Bit Width";
2290 uint32_t asm_bit_width_mode = 0;
2291
2292 if (enforce_mode == 0) {
2293 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2294 return;
2295 }
2296
2297 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2298 if (!ctl) {
2299 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2300 __func__, mixer_ctl_name);
2301 return;
2302 }
2303
2304 if (enable)
2305 asm_bit_width_mode = enforce_mode;
2306 else
2307 asm_bit_width_mode = 0;
2308
2309 ALOGV("%s DSP bit width feature status is %d width=%d",
2310 __func__, enable, asm_bit_width_mode);
2311 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2312 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2313 asm_bit_width_mode);
2314
2315 return;
2316}
2317
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302318/*
2319 * if native DSD playback active
2320 */
2321bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2322{
2323 bool active = false;
2324 struct listnode *node = NULL;
2325 struct audio_usecase *uc = NULL;
2326 struct stream_out *curr_out = NULL;
2327
2328 list_for_each(node, &adev->usecase_list) {
2329 uc = node_to_item(node, struct audio_usecase, list);
2330 curr_out = (struct stream_out*) uc->stream.out;
2331
2332 if (curr_out && PCM_PLAYBACK == uc->type &&
2333 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2334 active = true;
2335 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302336 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302337 }
2338 }
2339 return active;
2340}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302341
2342static bool force_device_switch(struct audio_usecase *usecase)
2343{
2344 bool ret = false;
2345 bool is_it_true_mode = false;
2346
Zhou Song30f2c3e2018-02-08 14:02:15 +08002347 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302348 usecase->type == TRANSCODE_LOOPBACK_RX ||
2349 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002350 return false;
2351 }
2352
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002353 if(usecase->stream.out == NULL) {
2354 ALOGE("%s: stream.out is NULL", __func__);
2355 return false;
2356 }
2357
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302358 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002359 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002360 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2361 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302362 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2363 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2364 (!is_it_true_mode && adev->native_playback_enabled)){
2365 ret = true;
2366 ALOGD("napb: time to toggle native mode");
2367 }
2368 }
2369
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302370 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302371 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2372 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002373 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302374 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302375 ALOGD("Force a2dp device switch to update new encoder config");
2376 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002377 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302378
Florian Pfister1a84f312018-07-19 14:38:18 +02002379 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302380 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2381 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002382 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302383 return ret;
2384}
2385
Aalique Grahame22e49102018-12-18 14:23:57 -08002386static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2387{
2388 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2389}
2390
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302391bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2392{
2393 bool ret=false;
2394 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002395 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2396 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302397 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2398 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002399 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302400 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002401 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2402 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302403 ret = true;
2404
2405 return ret;
2406}
2407
2408bool is_a2dp_device(snd_device_t out_snd_device)
2409{
2410 bool ret=false;
2411 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2412 ret = true;
2413
2414 return ret;
2415}
2416
2417bool is_bt_soc_on(struct audio_device *adev)
2418{
2419 struct mixer_ctl *ctl;
2420 char *mixer_ctl_name = "BT SOC status";
2421 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2422 bool bt_soc_status = true;
2423 if (!ctl) {
2424 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2425 __func__, mixer_ctl_name);
2426 /*This is to ensure we dont break targets which dont have the kernel change*/
2427 return true;
2428 }
2429 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2430 ALOGD("BT SOC status: %d",bt_soc_status);
2431 return bt_soc_status;
2432}
2433
Zhou Song331c8e52019-08-26 14:16:12 +08002434static int configure_btsco_sample_rate(snd_device_t snd_device)
2435{
2436 struct mixer_ctl *ctl = NULL;
2437 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2438 char *rate_str = NULL;
2439 bool is_rx_dev = true;
2440
2441 if (is_btsco_device(snd_device, snd_device)) {
2442 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2443 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2444 if (!ctl_sr_tx || !ctl_sr_rx) {
2445 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2446 if (!ctl_sr)
2447 return -ENOSYS;
2448 }
2449
2450 switch (snd_device) {
2451 case SND_DEVICE_OUT_BT_SCO:
2452 rate_str = "KHZ_8";
2453 break;
2454 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2455 case SND_DEVICE_IN_BT_SCO_MIC:
2456 rate_str = "KHZ_8";
2457 is_rx_dev = false;
2458 break;
2459 case SND_DEVICE_OUT_BT_SCO_WB:
2460 rate_str = "KHZ_16";
2461 break;
2462 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2463 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2464 rate_str = "KHZ_16";
2465 is_rx_dev = false;
2466 break;
2467 default:
2468 return 0;
2469 }
2470
2471 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2472 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2473 return -ENOSYS;
2474 }
2475 return 0;
2476}
2477
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302478int out_standby_l(struct audio_stream *stream);
2479
Eric Laurent637e2d42018-11-15 12:24:31 -08002480struct stream_in *adev_get_active_input(const struct audio_device *adev)
2481{
2482 struct listnode *node;
2483 struct stream_in *last_active_in = NULL;
2484
2485 /* Get last added active input.
2486 * TODO: We may use a priority mechanism to pick highest priority active source */
2487 list_for_each(node, &adev->usecase_list)
2488 {
2489 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2490 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2491 last_active_in = usecase->stream.in;
2492 }
2493
2494 return last_active_in;
2495}
2496
2497struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2498{
2499 struct listnode *node;
2500
2501 /* First check active inputs with voice communication source and then
2502 * any input if audio mode is in communication */
2503 list_for_each(node, &adev->usecase_list)
2504 {
2505 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2506 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2507 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2508 return usecase->stream.in;
2509 }
2510 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2511 return adev_get_active_input(adev);
2512
2513 return NULL;
2514}
2515
Carter Hsu2e429db2019-05-14 18:50:52 +08002516/*
2517 * Aligned with policy.h
2518 */
2519static inline int source_priority(int inputSource)
2520{
2521 switch (inputSource) {
2522 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2523 return 9;
2524 case AUDIO_SOURCE_CAMCORDER:
2525 return 8;
2526 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2527 return 7;
2528 case AUDIO_SOURCE_UNPROCESSED:
2529 return 6;
2530 case AUDIO_SOURCE_MIC:
2531 return 5;
2532 case AUDIO_SOURCE_ECHO_REFERENCE:
2533 return 4;
2534 case AUDIO_SOURCE_FM_TUNER:
2535 return 3;
2536 case AUDIO_SOURCE_VOICE_RECOGNITION:
2537 return 2;
2538 case AUDIO_SOURCE_HOTWORD:
2539 return 1;
2540 default:
2541 break;
2542 }
2543 return 0;
2544}
2545
2546static struct stream_in *get_priority_input(struct audio_device *adev)
2547{
2548 struct listnode *node;
2549 struct audio_usecase *usecase;
2550 int last_priority = 0, priority;
2551 struct stream_in *priority_in = NULL;
2552 struct stream_in *in;
2553
2554 list_for_each(node, &adev->usecase_list) {
2555 usecase = node_to_item(node, struct audio_usecase, list);
2556 if (usecase->type == PCM_CAPTURE) {
2557 in = usecase->stream.in;
2558 if (!in)
2559 continue;
2560 priority = source_priority(in->source);
2561
2562 if (priority > last_priority) {
2563 last_priority = priority;
2564 priority_in = in;
2565 }
2566 }
2567 }
2568 return priority_in;
2569}
2570
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002571int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002573 snd_device_t out_snd_device = SND_DEVICE_NONE;
2574 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002575 struct audio_usecase *usecase = NULL;
2576 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002577 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002578 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302579 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002580 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002581 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302583 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2584
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002585 usecase = get_usecase_from_list(adev, uc_id);
2586 if (usecase == NULL) {
2587 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2588 return -EINVAL;
2589 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002591 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002592 (usecase->type == VOIP_CALL) ||
2593 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302594 if(usecase->stream.out == NULL) {
2595 ALOGE("%s: stream.out is NULL", __func__);
2596 return -EINVAL;
2597 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002598 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002599 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2600 uc_id);
2601 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2602 uc_id);
2603 } else {
2604 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302605 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002606 in_snd_device = platform_get_input_snd_device(adev->platform,
2607 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302608 &usecase->stream.out->device_list,
2609 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002610 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002611 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302612 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302613 if (usecase->stream.inout == NULL) {
2614 ALOGE("%s: stream.inout is NULL", __func__);
2615 return -EINVAL;
2616 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002617 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302618 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2619 stream_out.format = usecase->stream.inout->out_config.format;
2620 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302621 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002622 assign_devices(&usecase->device_list,
2623 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302624 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2625 if (usecase->stream.inout == NULL) {
2626 ALOGE("%s: stream.inout is NULL", __func__);
2627 return -EINVAL;
2628 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302629 struct listnode out_devices;
2630 list_init(&out_devices);
2631 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2632 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002633 assign_devices(&usecase->device_list,
2634 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002635 } else {
2636 /*
2637 * If the voice call is active, use the sound devices of voice call usecase
2638 * so that it would not result any device switch. All the usecases will
2639 * be switched to new device when select_devices() is called for voice call
2640 * usecase. This is to avoid switching devices for voice call when
2641 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002642 * choose voice call device only if the use case device is
2643 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002644 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002645 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002646 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002647 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002648 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2649 is_codec_backend_out_device_type(&usecase->device_list)) ||
2650 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2651 is_codec_backend_in_device_type(&usecase->device_list)) ||
2652 is_single_device_type_equal(&vc_usecase->device_list,
2653 AUDIO_DEVICE_OUT_HEARING_AID) ||
2654 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002655 AUDIO_DEVICE_IN_VOICE_CALL) ||
2656 (is_single_device_type_equal(&usecase->device_list,
2657 AUDIO_DEVICE_IN_USB_HEADSET) &&
2658 is_single_device_type_equal(&vc_usecase->device_list,
2659 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002660 in_snd_device = vc_usecase->in_snd_device;
2661 out_snd_device = vc_usecase->out_snd_device;
2662 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002663 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002664 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002665 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002666 if ((voip_usecase != NULL) &&
2667 (usecase->type == PCM_PLAYBACK) &&
2668 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002669 out_snd_device_backend_match = platform_check_backends_match(
2670 voip_usecase->out_snd_device,
2671 platform_get_output_snd_device(
2672 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302673 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002674 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002675 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2676 (is_codec_backend_out_device_type(&usecase->device_list) ||
2677 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002678 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002679 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002680 in_snd_device = voip_usecase->in_snd_device;
2681 out_snd_device = voip_usecase->out_snd_device;
2682 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002683 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002684 hfp_ucid = audio_extn_hfp_get_usecase();
2685 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002686 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002687 in_snd_device = hfp_usecase->in_snd_device;
2688 out_snd_device = hfp_usecase->out_snd_device;
2689 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002690 }
2691 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302692 if (usecase->stream.out == NULL) {
2693 ALOGE("%s: stream.out is NULL", __func__);
2694 return -EINVAL;
2695 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002696 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002697 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002698 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002699 struct stream_out *voip_out = adev->primary_output;
2700 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002701 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002702 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2703 else
2704 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302705 usecase->stream.out,
2706 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002707 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002708
Eric Laurent637e2d42018-11-15 12:24:31 -08002709 if (voip_usecase)
2710 voip_out = voip_usecase->stream.out;
2711
2712 if (usecase->stream.out == voip_out && voip_in != NULL)
2713 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002714 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002715 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302716 if (usecase->stream.in == NULL) {
2717 ALOGE("%s: stream.in is NULL", __func__);
2718 return -EINVAL;
2719 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002720 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002721 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002722 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002723 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002724 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002725 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002726
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002727 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002728 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002729 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2730 USECASE_AUDIO_PLAYBACK_VOIP);
2731
Carter Hsu2e429db2019-05-14 18:50:52 +08002732 usecase->stream.in->enable_ec_port = false;
2733
Zhou Song62ea0282020-03-22 19:53:01 +08002734 bool is_ha_usecase = adev->ha_proxy_enable ?
2735 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2736 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2737 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002738 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002739 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002740 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002741 } else if (adev->primary_output &&
2742 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002743 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002744 } else {
2745 /* forcing speaker o/p device to get matching i/p pair
2746 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002747 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002748 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002749 priority_in = voip_in;
2750 } else {
2751 /* get the input with the highest priority source*/
2752 priority_in = get_priority_input(adev);
2753
2754 if (!priority_in)
2755 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002756 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002757
Eric Laurent637e2d42018-11-15 12:24:31 -08002758 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002759 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302760 &out_devices,
2761 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002762 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002763 }
2764 }
2765
2766 if (out_snd_device == usecase->out_snd_device &&
2767 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302768
2769 if (!force_device_switch(usecase))
2770 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771 }
2772
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002773 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002774 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002775 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002776 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2777 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302778 }
2779
Aalique Grahame22e49102018-12-18 14:23:57 -08002780 if (out_snd_device != SND_DEVICE_NONE &&
2781 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2782 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2783 __func__,
2784 use_case_table[uc_id],
2785 adev->last_logged_snd_device[uc_id][0],
2786 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2787 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2788 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2789 -1,
2790 out_snd_device,
2791 platform_get_snd_device_name(out_snd_device),
2792 platform_get_snd_device_acdb_id(out_snd_device));
2793 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2794 }
2795 if (in_snd_device != SND_DEVICE_NONE &&
2796 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2797 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2798 __func__,
2799 use_case_table[uc_id],
2800 adev->last_logged_snd_device[uc_id][1],
2801 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2802 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2803 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2804 -1,
2805 in_snd_device,
2806 platform_get_snd_device_name(in_snd_device),
2807 platform_get_snd_device_acdb_id(in_snd_device));
2808 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2809 }
2810
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812 /*
2813 * Limitation: While in call, to do a device switch we need to disable
2814 * and enable both RX and TX devices though one of them is same as current
2815 * device.
2816 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002817 if ((usecase->type == VOICE_CALL) &&
2818 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2819 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002820 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002821 }
2822
2823 if (((usecase->type == VOICE_CALL) ||
2824 (usecase->type == VOIP_CALL)) &&
2825 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2826 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302827 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002828 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002829 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002830
2831 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302832 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002833 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002834 }
2835
Aalique Grahame22e49102018-12-18 14:23:57 -08002836 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2837 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002838 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302839 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002840 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2841 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2842 else
2843 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302844 }
2845
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002846 /* Disable current sound devices */
2847 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002848 disable_audio_route(adev, usecase);
2849 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002850 }
2851
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002852 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002853 disable_audio_route(adev, usecase);
2854 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855 }
2856
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002857 /* Applicable only on the targets that has external modem.
2858 * New device information should be sent to modem before enabling
2859 * the devices to reduce in-call device switch time.
2860 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002861 if ((usecase->type == VOICE_CALL) &&
2862 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2863 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002864 status = platform_switch_voice_call_enable_device_config(adev->platform,
2865 out_snd_device,
2866 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002867 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002868
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002869 /* Enable new sound devices */
2870 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002871 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302872 if (platform_check_codec_asrc_support(adev->platform))
2873 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002874 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 }
2876
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002877 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302878 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002879 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002880 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002881
Avinash Vaish71a8b972014-07-24 15:36:33 +05302882 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002883 status = platform_switch_voice_call_device_post(adev->platform,
2884 out_snd_device,
2885 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302886 enable_audio_route_for_voice_usecases(adev, usecase);
2887 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002888
sangwoo170731f2013-06-08 15:36:36 +09002889 usecase->in_snd_device = in_snd_device;
2890 usecase->out_snd_device = out_snd_device;
2891
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302892 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2893 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302894 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002895 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002896 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002897 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2898 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2899 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2900 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2901 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2902 /*
2903 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2904 * configured device sample rate, if not update the COPP rate to be equal to the
2905 * device sample rate, else open COPP at stream sample rate
2906 */
2907 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2908 usecase->stream.out->sample_rate,
2909 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302910 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302911 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2912 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302913 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002914 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2915 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2916 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2917 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002918 }
2919 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002920
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002921 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002922
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002923 /* If input stream is already running then effect needs to be
2924 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002925 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002926 check_and_enable_effect(adev);
2927
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002928 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002929 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302930 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002931 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2932
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002933 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302934 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002935 voice_extn_compress_voip_is_started(adev))
2936 voice_set_sidetone(adev, out_snd_device, true);
2937 }
2938
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002939 /* Applicable only on the targets that has external modem.
2940 * Enable device command should be sent to modem only after
2941 * enabling voice call mixer controls
2942 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002943 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002944 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2945 out_snd_device,
2946 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302947
2948 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002949 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302950 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002951 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302952 if (is_bt_soc_on(adev) == false){
2953 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002954 if (in->pcm != NULL)
2955 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302956 }
2957 }
2958 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2959 && usecase->stream.out->started) {
2960 if (is_bt_soc_on(adev) == false) {
2961 ALOGD("BT SCO/A2DP disconnected while in connection");
2962 out_standby_l(&usecase->stream.out->stream.common);
2963 }
2964 }
2965 } else if ((usecase->stream.out != NULL) &&
2966 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302967 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2968 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08002969 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302970 usecase->stream.out->started) {
2971 if (is_bt_soc_on(adev) == false) {
2972 ALOGD("BT SCO/A2dp disconnected while in connection");
2973 out_standby_l(&usecase->stream.out->stream.common);
2974 }
2975 }
2976 }
2977
Yung Ti Su70cb8242018-06-22 17:38:47 +08002978 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002979 struct stream_out *voip_out = voip_usecase->stream.out;
2980 audio_extn_utils_send_app_type_gain(adev,
2981 voip_out->app_type_cfg.app_type,
2982 &voip_out->app_type_cfg.gain[0]);
2983 }
2984
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302985 ALOGD("%s: done",__func__);
2986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987 return status;
2988}
2989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990static int stop_input_stream(struct stream_in *in)
2991{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302992 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302994
2995 if (in == NULL) {
2996 ALOGE("%s: stream_in ptr is NULL", __func__);
2997 return -EINVAL;
2998 }
2999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003001 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002
Eric Laurent994a6932013-07-17 11:51:42 -07003003 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003004 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 uc_info = get_usecase_from_list(adev, in->usecase);
3006 if (uc_info == NULL) {
3007 ALOGE("%s: Could not find the usecase (%d) in the list",
3008 __func__, in->usecase);
3009 return -EINVAL;
3010 }
3011
Carter Hsu2e429db2019-05-14 18:50:52 +08003012 priority_in = get_priority_input(adev);
3013
Derek Chenea197282019-01-07 17:35:01 -08003014 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3015 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003016
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003017 /* Close in-call recording streams */
3018 voice_check_and_stop_incall_rec_usecase(adev, in);
3019
Eric Laurent150dbfe2013-02-27 14:31:02 -08003020 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003021 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003022
3023 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003024 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003026 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303027 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3028
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003029 list_remove(&uc_info->list);
3030 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031
Carter Hsu2e429db2019-05-14 18:50:52 +08003032 if (priority_in == in) {
3033 priority_in = get_priority_input(adev);
3034 if (priority_in)
3035 select_devices(adev, priority_in->usecase);
3036 }
3037
Vatsal Buchac09ae062018-11-14 13:25:08 +05303038 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003039 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 return ret;
3041}
3042
3043int start_input_stream(struct stream_in *in)
3044{
3045 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003046 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303048
3049 if (in == NULL) {
3050 ALOGE("%s: stream_in ptr is NULL", __func__);
3051 return -EINVAL;
3052 }
3053
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003055 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003056 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057
Mingming Yin2664a5b2015-09-03 10:53:11 -07003058 if (get_usecase_from_list(adev, usecase) == NULL)
3059 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303060 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3061 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003062
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303063 if (CARD_STATUS_OFFLINE == in->card_status||
3064 CARD_STATUS_OFFLINE == adev->card_status) {
3065 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303066 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303067 goto error_config;
3068 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303069
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003070 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303071 if (!adev->bt_sco_on) {
3072 ALOGE("%s: SCO profile is not ready, return error", __func__);
3073 ret = -EIO;
3074 goto error_config;
3075 }
3076 }
3077
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003078 /* Check if source matches incall recording usecase criteria */
3079 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3080 if (ret)
3081 goto error_config;
3082 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003083 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3084
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303085 if (audio_extn_cin_attached_usecase(in))
3086 audio_extn_cin_acquire_usecase(in);
3087
Mingming Yin2664a5b2015-09-03 10:53:11 -07003088 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3089 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3090 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003091 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003092 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003093
Eric Laurentb23d5282013-05-14 15:27:20 -07003094 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 if (in->pcm_device_id < 0) {
3096 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3097 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003098 ret = -EINVAL;
3099 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003103
3104 if (!uc_info) {
3105 ret = -ENOMEM;
3106 goto error_config;
3107 }
3108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109 uc_info->id = in->usecase;
3110 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003111 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003112 list_init(&uc_info->device_list);
3113 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003114 uc_info->in_snd_device = SND_DEVICE_NONE;
3115 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003117 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003118 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303119 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3120 adev->perf_lock_opts,
3121 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003122 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123
Derek Chenea197282019-01-07 17:35:01 -08003124 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3125 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003126
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303127 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3128
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303129 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303130 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303131 if (ret)
3132 goto error_open;
3133 else
3134 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003135 }
3136
Haynes Mathew George16081042017-05-31 17:16:49 -07003137 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003138 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003139 ALOGE("%s: pcm stream not ready", __func__);
3140 goto error_open;
3141 }
3142 ret = pcm_start(in->pcm);
3143 if (ret < 0) {
3144 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3145 goto error_open;
3146 }
3147 } else {
3148 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3149 unsigned int pcm_open_retry_count = 0;
3150
Zhou Song62ea0282020-03-22 19:53:01 +08003151 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3152 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003153 flags |= PCM_MMAP | PCM_NOIRQ;
3154 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3155 } else if (in->realtime) {
3156 flags |= PCM_MMAP | PCM_NOIRQ;
3157 }
3158
Garmond Leunge2433c32017-09-28 21:51:22 -07003159 if (audio_extn_ffv_get_stream() == in) {
3160 ALOGD("%s: ffv stream, update pcm config", __func__);
3161 audio_extn_ffv_update_pcm_config(&config);
3162 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003163 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3164 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3165
3166 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003167 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003168 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003169 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003170 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303171 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303172 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3173 adev->card_status = CARD_STATUS_OFFLINE;
3174 in->card_status = CARD_STATUS_OFFLINE;
3175 ret = -EIO;
3176 goto error_open;
3177 }
3178
Haynes Mathew George16081042017-05-31 17:16:49 -07003179 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3180 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3181 if (in->pcm != NULL) {
3182 pcm_close(in->pcm);
3183 in->pcm = NULL;
3184 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003185 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003186 ret = -EIO;
3187 goto error_open;
3188 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003189 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003190 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3191 continue;
3192 }
3193 break;
3194 }
3195
3196 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003197 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003198 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003199 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003200 if (ret < 0) {
3201 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3202 pcm_close(in->pcm);
3203 in->pcm = NULL;
3204 goto error_open;
3205 }
3206 register_in_stream(in);
3207 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003208 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003209 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003210 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003211 if (ret < 0) {
3212 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003213 pcm_close(in->pcm);
3214 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003215 goto error_open;
3216 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003217 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003218 }
3219
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003220 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003221 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3222 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003223
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003224 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303225 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3226
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303227done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003228 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303229 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003230 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303231 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003232 return ret;
3233
3234error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003235 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303236 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003238
Eric Laurentc8400632013-02-14 19:04:54 -08003239error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303240 /*
3241 * sleep 50ms to allow sufficient time for kernel
3242 * drivers to recover incases like SSR.
3243 */
3244 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003245 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303246 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003247 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248}
3249
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003250void lock_input_stream(struct stream_in *in)
3251{
3252 pthread_mutex_lock(&in->pre_lock);
3253 pthread_mutex_lock(&in->lock);
3254 pthread_mutex_unlock(&in->pre_lock);
3255}
3256
3257void lock_output_stream(struct stream_out *out)
3258{
3259 pthread_mutex_lock(&out->pre_lock);
3260 pthread_mutex_lock(&out->lock);
3261 pthread_mutex_unlock(&out->pre_lock);
3262}
3263
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003264/* must be called with out->lock locked */
3265static int send_offload_cmd_l(struct stream_out* out, int command)
3266{
3267 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3268
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003269 if (!cmd) {
3270 ALOGE("failed to allocate mem for command 0x%x", command);
3271 return -ENOMEM;
3272 }
3273
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003274 ALOGVV("%s %d", __func__, command);
3275
3276 cmd->cmd = command;
3277 list_add_tail(&out->offload_cmd_list, &cmd->node);
3278 pthread_cond_signal(&out->offload_cond);
3279 return 0;
3280}
3281
3282/* must be called iwth out->lock locked */
3283static void stop_compressed_output_l(struct stream_out *out)
3284{
3285 out->offload_state = OFFLOAD_STATE_IDLE;
3286 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003287 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003288 if (out->compr != NULL) {
3289 compress_stop(out->compr);
3290 while (out->offload_thread_blocked) {
3291 pthread_cond_wait(&out->cond, &out->lock);
3292 }
3293 }
3294}
3295
Varun Balaraje49253e2017-07-06 19:48:56 +05303296bool is_interactive_usecase(audio_usecase_t uc_id)
3297{
3298 unsigned int i;
3299 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3300 if (uc_id == interactive_usecases[i])
3301 return true;
3302 }
3303 return false;
3304}
3305
3306static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3307{
3308 audio_usecase_t ret_uc = USECASE_INVALID;
3309 unsigned int intract_uc_index;
3310 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3311
3312 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3313 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3314 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3315 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3316 ret_uc = interactive_usecases[intract_uc_index];
3317 break;
3318 }
3319 }
3320
3321 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3322 return ret_uc;
3323}
3324
3325static void free_interactive_usecase(struct audio_device *adev,
3326 audio_usecase_t uc_id)
3327{
3328 unsigned int interact_uc_index;
3329 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3330
3331 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3332 if (interactive_usecases[interact_uc_index] == uc_id) {
3333 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3334 break;
3335 }
3336 }
3337 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3338}
3339
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003340bool is_offload_usecase(audio_usecase_t uc_id)
3341{
3342 unsigned int i;
3343 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3344 if (uc_id == offload_usecases[i])
3345 return true;
3346 }
3347 return false;
3348}
3349
Dhananjay Kumarac341582017-02-23 23:42:25 +05303350static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003351{
vivek mehta446c3962015-09-14 10:57:35 -07003352 audio_usecase_t ret_uc = USECASE_INVALID;
3353 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003354 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003355 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303356 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003357 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3358 else
3359 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003360
vivek mehta446c3962015-09-14 10:57:35 -07003361 pthread_mutex_lock(&adev->lock);
3362 if (get_usecase_from_list(adev, ret_uc) != NULL)
3363 ret_uc = USECASE_INVALID;
3364 pthread_mutex_unlock(&adev->lock);
3365
3366 return ret_uc;
3367 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003368
3369 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003370 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3371 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3372 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3373 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003374 break;
3375 }
3376 }
vivek mehta446c3962015-09-14 10:57:35 -07003377
3378 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3379 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003380}
3381
3382static void free_offload_usecase(struct audio_device *adev,
3383 audio_usecase_t uc_id)
3384{
vivek mehta446c3962015-09-14 10:57:35 -07003385 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003386 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003387
3388 if (!adev->multi_offload_enable)
3389 return;
3390
3391 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3392 if (offload_usecases[offload_uc_index] == uc_id) {
3393 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003394 break;
3395 }
3396 }
3397 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3398}
3399
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003400static void *offload_thread_loop(void *context)
3401{
3402 struct stream_out *out = (struct stream_out *) context;
3403 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003404 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003405
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003406 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003407 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003408 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3409
3410 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003411 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003412 out->offload_state = OFFLOAD_STATE_IDLE;
3413 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003414 for (;;) {
3415 struct offload_cmd *cmd = NULL;
3416 stream_callback_event_t event;
3417 bool send_callback = false;
3418
3419 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3420 __func__, list_empty(&out->offload_cmd_list),
3421 out->offload_state);
3422 if (list_empty(&out->offload_cmd_list)) {
3423 ALOGV("%s SLEEPING", __func__);
3424 pthread_cond_wait(&out->offload_cond, &out->lock);
3425 ALOGV("%s RUNNING", __func__);
3426 continue;
3427 }
3428
3429 item = list_head(&out->offload_cmd_list);
3430 cmd = node_to_item(item, struct offload_cmd, node);
3431 list_remove(item);
3432
3433 ALOGVV("%s STATE %d CMD %d out->compr %p",
3434 __func__, out->offload_state, cmd->cmd, out->compr);
3435
3436 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3437 free(cmd);
3438 break;
3439 }
3440
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003441 // allow OFFLOAD_CMD_ERROR reporting during standby
3442 // this is needed to handle failures during compress_open
3443 // Note however that on a pause timeout, the stream is closed
3444 // and no offload usecase will be active. Therefore this
3445 // special case is needed for compress_open failures alone
3446 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3447 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003448 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003449 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003450 pthread_cond_signal(&out->cond);
3451 continue;
3452 }
3453 out->offload_thread_blocked = true;
3454 pthread_mutex_unlock(&out->lock);
3455 send_callback = false;
3456 switch(cmd->cmd) {
3457 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003458 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003459 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003460 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003461 send_callback = true;
3462 event = STREAM_CBK_EVENT_WRITE_READY;
3463 break;
3464 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003465 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303466 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003467 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303468 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003469 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303470 if (ret < 0)
3471 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303472 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303473 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003474 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003475 else
3476 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003477 if (-ENETRESET != ret && !(-EINTR == ret &&
3478 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303479 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303480 pthread_mutex_lock(&out->lock);
3481 out->send_new_metadata = 1;
3482 out->send_next_track_params = true;
3483 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303484 event = STREAM_CBK_EVENT_DRAIN_READY;
3485 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3486 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303487 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003488 break;
3489 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003490 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003491 ret = compress_drain(out->compr);
3492 ALOGD("copl(%p):out of compress_drain", out);
3493 // EINTR check avoids drain interruption due to SSR
3494 if (-ENETRESET != ret && !(-EINTR == ret &&
3495 CARD_STATUS_OFFLINE == out->card_status)) {
3496 send_callback = true;
3497 event = STREAM_CBK_EVENT_DRAIN_READY;
3498 } else
3499 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003500 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303501 case OFFLOAD_CMD_ERROR:
3502 ALOGD("copl(%p): sending error callback to AF", out);
3503 send_callback = true;
3504 event = STREAM_CBK_EVENT_ERROR;
3505 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003506 default:
3507 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3508 break;
3509 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003510 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003511 out->offload_thread_blocked = false;
3512 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003513 if (send_callback && out->client_callback) {
3514 ALOGVV("%s: sending client_callback event %d", __func__, event);
3515 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003516 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003517 free(cmd);
3518 }
3519
3520 pthread_cond_signal(&out->cond);
3521 while (!list_empty(&out->offload_cmd_list)) {
3522 item = list_head(&out->offload_cmd_list);
3523 list_remove(item);
3524 free(node_to_item(item, struct offload_cmd, node));
3525 }
3526 pthread_mutex_unlock(&out->lock);
3527
3528 return NULL;
3529}
3530
3531static int create_offload_callback_thread(struct stream_out *out)
3532{
3533 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3534 list_init(&out->offload_cmd_list);
3535 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3536 offload_thread_loop, out);
3537 return 0;
3538}
3539
3540static int destroy_offload_callback_thread(struct stream_out *out)
3541{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003542 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003543 stop_compressed_output_l(out);
3544 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3545
3546 pthread_mutex_unlock(&out->lock);
3547 pthread_join(out->offload_thread, (void **) NULL);
3548 pthread_cond_destroy(&out->offload_cond);
3549
3550 return 0;
3551}
3552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553static int stop_output_stream(struct stream_out *out)
3554{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303555 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 struct audio_usecase *uc_info;
3557 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003558 bool has_voip_usecase =
3559 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560
Eric Laurent994a6932013-07-17 11:51:42 -07003561 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003562 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 uc_info = get_usecase_from_list(adev, out->usecase);
3564 if (uc_info == NULL) {
3565 ALOGE("%s: Could not find the usecase (%d) in the list",
3566 __func__, out->usecase);
3567 return -EINVAL;
3568 }
3569
Derek Chenea197282019-01-07 17:35:01 -08003570 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3571 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003572
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003573 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303574 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003575 if (adev->visualizer_stop_output != NULL)
3576 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003577
3578 audio_extn_dts_remove_state_notifier_node(out->usecase);
3579
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003580 if (adev->offload_effects_stop_output != NULL)
3581 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003582 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3583 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3584 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003585 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003586
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003587 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3588 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003589 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003590 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003591
Eric Laurent150dbfe2013-02-27 14:31:02 -08003592 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003593 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003594
3595 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003596 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597
Aalique Grahame22e49102018-12-18 14:23:57 -08003598 audio_extn_extspk_update(adev->extspk);
3599
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003600 if (is_offload_usecase(out->usecase)) {
3601 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3602 adev->dsp_bit_width_enforce_mode,
3603 false);
3604 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003605 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003606 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3607 false);
3608
3609 if (ret != 0)
3610 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3611 /* default service interval was successfully updated,
3612 reopen USB backend with new service interval */
3613 ret = 0;
3614 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003615
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003616 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303617 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003618 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303619 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003620 ALOGV("Disable passthrough , reset mixer to pcm");
3621 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003622#ifdef AUDIO_GKI_ENABLED
3623 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3624 out->compr_config.codec->reserved[0] = 0;
3625#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003626 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003627#endif
Mingming Yin21854652016-04-13 11:54:02 -07003628 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003629 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3630 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003631
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303632 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003633 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303634 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303635
Manish Dewangan21a850a2017-08-14 12:03:55 +05303636 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003637 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3638 if (ret < 0)
3639 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3640 }
3641
juyuchen2d415992018-11-16 14:15:16 +08003642 /* 1) media + voip output routing to handset must route media back to
3643 speaker when voip stops.
3644 2) trigger voip input to reroute when voip output changes to
3645 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003646 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003647 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003648 struct listnode *node;
3649 struct audio_usecase *usecase;
3650 list_for_each(node, &adev->usecase_list) {
3651 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003652 if ((usecase->type == PCM_CAPTURE &&
3653 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3654 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003655 continue;
3656
3657 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3658 __func__, usecase->id, use_case_table[usecase->id],
3659 out->usecase, use_case_table[out->usecase]);
3660 select_devices(adev, usecase->id);
3661 }
3662 }
3663
Garmond Leung5fd0b552018-04-17 11:56:12 -07003664 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003665 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003666 return ret;
3667}
3668
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003669struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3670 unsigned int flags, unsigned int pcm_open_retry_count,
3671 struct pcm_config *config)
3672{
3673 struct pcm* pcm = NULL;
3674
3675 while (1) {
3676 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3677 if (pcm == NULL || !pcm_is_ready(pcm)) {
3678 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3679 if (pcm != NULL) {
3680 pcm_close(pcm);
3681 pcm = NULL;
3682 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003683 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003684 return NULL;
3685
Weiyin Jiang72197252019-10-09 11:49:32 +08003686 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003687 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3688 continue;
3689 }
3690 break;
3691 }
3692
3693 if (pcm_is_ready(pcm)) {
3694 int ret = pcm_prepare(pcm);
3695 if (ret < 0) {
3696 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3697 pcm_close(pcm);
3698 pcm = NULL;
3699 }
3700 }
3701
3702 return pcm;
3703}
3704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705int start_output_stream(struct stream_out *out)
3706{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 struct audio_usecase *uc_info;
3709 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003710 char mixer_ctl_name[128];
3711 struct mixer_ctl *ctl = NULL;
3712 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303713 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003714 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715
Haynes Mathew George380745d2017-10-04 15:27:45 -07003716 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003717 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3718 ret = -EINVAL;
3719 goto error_config;
3720 }
3721
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003722 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303723 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003724 get_device_types(&out->device_list), is_haptic_usecase);
3725
3726 bool is_speaker_active = compare_device_type(&out->device_list,
3727 AUDIO_DEVICE_OUT_SPEAKER);
3728 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3729 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303730
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303731 if (CARD_STATUS_OFFLINE == out->card_status ||
3732 CARD_STATUS_OFFLINE == adev->card_status) {
3733 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303734 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003735 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303736 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303737
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003738 //Update incall music usecase to reflect correct voice session
3739 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3740 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3741 if (ret != 0) {
3742 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3743 __func__, ret);
3744 goto error_config;
3745 }
3746 }
3747
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003748 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003749 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003750 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303751 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303752 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303753 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3754 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3755 ret = -EAGAIN;
3756 goto error_config;
3757 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303758 }
3759 }
3760 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003761 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303762 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003763 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303764 //combo usecase just by pass a2dp
3765 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003766 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303767 } else {
3768 ALOGE("%s: SCO profile is not ready, return error", __func__);
3769 ret = -EAGAIN;
3770 goto error_config;
3771 }
3772 }
3773 }
3774
Eric Laurentb23d5282013-05-14 15:27:20 -07003775 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776 if (out->pcm_device_id < 0) {
3777 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3778 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003779 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003780 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 }
3782
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003783 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003784 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3785 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003786 if (adev->haptic_pcm_device_id < 0) {
3787 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3788 __func__, adev->haptic_pcm_device_id, out->usecase);
3789 ret = -EINVAL;
3790 goto error_config;
3791 }
3792 }
3793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003795
3796 if (!uc_info) {
3797 ret = -ENOMEM;
3798 goto error_config;
3799 }
3800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 uc_info->id = out->usecase;
3802 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003803 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003804 list_init(&uc_info->device_list);
3805 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003806 uc_info->in_snd_device = SND_DEVICE_NONE;
3807 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003808
3809 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003810 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003811 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3812 /* USB backend is not reopened immediately.
3813 This is eventually done as part of select_devices */
3814 }
3815
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003816 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817
Wei Wangf7ca6c92017-11-21 14:51:20 -08003818 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303819 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3820 adev->perf_lock_opts,
3821 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303822
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003823 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303824 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303825 if (audio_extn_passthru_is_enabled() &&
3826 audio_extn_passthru_is_passthrough_stream(out)) {
3827 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303828 }
3829 }
3830
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003831 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003832 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303833 if (!a2dp_combo) {
3834 check_a2dp_restore_l(adev, out, false);
3835 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003836 struct listnode dev;
3837 list_init(&dev);
3838 assign_devices(&dev, &out->device_list);
3839 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3840 reassign_device_list(&out->device_list,
3841 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003842 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003843 reassign_device_list(&out->device_list,
3844 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303845 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003846 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303847 }
3848 } else {
3849 select_devices(adev, out->usecase);
3850 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003851
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003852 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3853 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003854 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003855 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003856
Derek Chenea197282019-01-07 17:35:01 -08003857 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3858 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003859
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003860 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3861 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003862
3863 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003864 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003865 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3866 ALOGE("%s: pcm stream not ready", __func__);
3867 goto error_open;
3868 }
3869 ret = pcm_start(out->pcm);
3870 if (ret < 0) {
3871 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3872 goto error_open;
3873 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003874 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003875 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003876 unsigned int flags = PCM_OUT;
3877 unsigned int pcm_open_retry_count = 0;
3878 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3879 flags |= PCM_MMAP | PCM_NOIRQ;
3880 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003881 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003882 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003883 } else
3884 flags |= PCM_MONOTONIC;
3885
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003886 if ((adev->vr_audio_mode_enabled) &&
3887 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3888 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3889 "PCM_Dev %d Topology", out->pcm_device_id);
3890 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3891 if (!ctl) {
3892 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3893 __func__, mixer_ctl_name);
3894 } else {
3895 //if success use ULLPP
3896 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3897 __func__, mixer_ctl_name, out->pcm_device_id);
3898 //There is a still a possibility that some sessions
3899 // that request for FAST|RAW when 3D audio is active
3900 //can go through ULLPP. Ideally we expects apps to
3901 //listen to audio focus and stop concurrent playback
3902 //Also, we will look for mode flag (voice_in_communication)
3903 //before enabling the realtime flag.
3904 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3905 }
3906 }
3907
Surendar Karka91fa3682018-07-02 18:12:12 +05303908 if (out->realtime)
3909 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3910 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3911
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003912 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3913 flags, pcm_open_retry_count,
3914 &(out->config));
3915 if (out->pcm == NULL) {
3916 ret = -EIO;
3917 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003918 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003919
3920 if (is_haptic_usecase) {
3921 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3922 adev->haptic_pcm_device_id,
3923 flags, pcm_open_retry_count,
3924 &(adev->haptics_config));
3925 // failure to open haptics pcm shouldnt stop audio,
3926 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003927
3928 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3929 ALOGD("%s: enable haptic audio synchronization", __func__);
3930 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3931 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003932 }
3933
Surendar Karka91fa3682018-07-02 18:12:12 +05303934 if (!out->realtime)
3935 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303936 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003937
Zhou Song2b8f28f2017-09-11 10:51:38 +08003938 // apply volume for voip playback after path is set up
3939 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3940 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303941 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3942 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303943 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3944 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003945 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3946 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303947 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003948 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08003949 /*
3950 * set custom channel map if:
3951 * 1. neither mono nor stereo clips i.e. channels > 2 OR
3952 * 2. custom channel map has been set by client
3953 * else default channel map of FC/FR/FL can always be set to DSP
3954 */
3955 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
3956 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3957 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003958 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3959 adev->dsp_bit_width_enforce_mode,
3960 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003962 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003963 out->compr = compress_open(adev->snd_card,
3964 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003965 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003966 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303967 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303968 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3969 adev->card_status = CARD_STATUS_OFFLINE;
3970 out->card_status = CARD_STATUS_OFFLINE;
3971 ret = -EIO;
3972 goto error_open;
3973 }
3974
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003975 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003976 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003977 compress_close(out->compr);
3978 out->compr = NULL;
3979 ret = -EIO;
3980 goto error_open;
3981 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303982 /* compress_open sends params of the track, so reset the flag here */
3983 out->is_compr_metadata_avail = false;
3984
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003985 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003986 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003987
Fred Oh3f43e742015-03-04 18:42:34 -08003988 /* Since small bufs uses blocking writes, a write will be blocked
3989 for the default max poll time (20s) in the event of an SSR.
3990 Reduce the poll time to observe and deal with SSR faster.
3991 */
Ashish Jain5106d362016-05-11 19:23:33 +05303992 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003993 compress_set_max_poll_wait(out->compr, 1000);
3994 }
3995
Manish Dewangan69426c82017-01-30 17:35:36 +05303996 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303997 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303998
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003999 audio_extn_dts_create_state_notifier_node(out->usecase);
4000 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4001 popcount(out->channel_mask),
4002 out->playback_started);
4003
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004004#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304005 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004006 audio_extn_dolby_send_ddp_endp_params(adev);
4007#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304008 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4009 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004010 if (adev->visualizer_start_output != NULL)
4011 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4012 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304013 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004014 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004015 }
Derek Chenf13dd492018-11-13 14:53:51 -08004016
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004017 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004018 /* Update cached volume from media to offload/direct stream */
4019 struct listnode *node = NULL;
4020 list_for_each(node, &adev->active_outputs_list) {
4021 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4022 streams_output_ctxt_t,
4023 list);
4024 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4025 out->volume_l = out_ctxt->output->volume_l;
4026 out->volume_r = out_ctxt->output->volume_r;
4027 }
4028 }
4029 out_set_compr_volume(&out->stream,
4030 out->volume_l, out->volume_r);
4031 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004032 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004033
4034 if (ret == 0) {
4035 register_out_stream(out);
4036 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004037 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4038 ALOGE("%s: pcm stream not ready", __func__);
4039 goto error_open;
4040 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004041 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004042 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004043 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004044 if (ret < 0)
4045 goto error_open;
4046 }
4047 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004048 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304049 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004050 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004051
vivek mehtad15d2bf2019-05-17 13:35:10 -07004052 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4053 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4054 audio_low_latency_hint_start();
4055 }
4056
Manish Dewangan21a850a2017-08-14 12:03:55 +05304057 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004058 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004059 if (ret < 0)
4060 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4061 }
4062
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004063 // consider a scenario where on pause lower layers are tear down.
4064 // so on resume, swap mixer control need to be sent only when
4065 // backend is active, hence rather than sending from enable device
4066 // sending it from start of streamtream
4067
4068 platform_set_swap_channels(adev, true);
4069
Haynes Mathew George380745d2017-10-04 15:27:45 -07004070 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304071 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004072 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004073error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004074 if (adev->haptic_pcm) {
4075 pcm_close(adev->haptic_pcm);
4076 adev->haptic_pcm = NULL;
4077 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004078 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304079 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004080 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004081error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304082 /*
4083 * sleep 50ms to allow sufficient time for kernel
4084 * drivers to recover incases like SSR.
4085 */
4086 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004087error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004088 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304089 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004090 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091}
4092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093static int check_input_parameters(uint32_t sample_rate,
4094 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004095 int channel_count,
4096 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004097{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004098 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004099
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304100 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4101 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4102 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004103 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004104 !audio_extn_compr_cap_format_supported(format) &&
4105 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004106 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004107
Aalique Grahame22e49102018-12-18 14:23:57 -08004108 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4109 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4110 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4111 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4112 return -EINVAL;
4113 }
4114
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004115 switch (channel_count) {
4116 case 1:
4117 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304118 case 3:
4119 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004120 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004121 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304122 case 10:
4123 case 12:
4124 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004125 break;
4126 default:
4127 ret = -EINVAL;
4128 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004129
4130 switch (sample_rate) {
4131 case 8000:
4132 case 11025:
4133 case 12000:
4134 case 16000:
4135 case 22050:
4136 case 24000:
4137 case 32000:
4138 case 44100:
4139 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004140 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304141 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004142 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304143 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144 break;
4145 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004146 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147 }
4148
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004149 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004150}
4151
Naresh Tanniru04f71882018-06-26 17:46:22 +05304152
4153/** Add a value in a list if not already present.
4154 * @return true if value was successfully inserted or already present,
4155 * false if the list is full and does not contain the value.
4156 */
4157static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4158 for (size_t i = 0; i < list_length; i++) {
4159 if (list[i] == value) return true; // value is already present
4160 if (list[i] == 0) { // no values in this slot
4161 list[i] = value;
4162 return true; // value inserted
4163 }
4164 }
4165 return false; // could not insert value
4166}
4167
4168/** Add channel_mask in supported_channel_masks if not already present.
4169 * @return true if channel_mask was successfully inserted or already present,
4170 * false if supported_channel_masks is full and does not contain channel_mask.
4171 */
4172static void register_channel_mask(audio_channel_mask_t channel_mask,
4173 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4174 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4175 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4176}
4177
4178/** Add format in supported_formats if not already present.
4179 * @return true if format was successfully inserted or already present,
4180 * false if supported_formats is full and does not contain format.
4181 */
4182static void register_format(audio_format_t format,
4183 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4184 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4185 "%s: stream can not declare supporting its format %x", __func__, format);
4186}
4187/** Add sample_rate in supported_sample_rates if not already present.
4188 * @return true if sample_rate was successfully inserted or already present,
4189 * false if supported_sample_rates is full and does not contain sample_rate.
4190 */
4191static void register_sample_rate(uint32_t sample_rate,
4192 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4193 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4194 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4195}
4196
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004197static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4198{
4199 uint32_t high = num1, low = num2, temp = 0;
4200
4201 if (!num1 || !num2)
4202 return 0;
4203
4204 if (num1 < num2) {
4205 high = num2;
4206 low = num1;
4207 }
4208
4209 while (low != 0) {
4210 temp = low;
4211 low = high % low;
4212 high = temp;
4213 }
4214 return (num1 * num2)/high;
4215}
4216
4217static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4218{
4219 uint32_t remainder = 0;
4220
4221 if (!multiplier)
4222 return num;
4223
4224 remainder = num % multiplier;
4225 if (remainder)
4226 num += (multiplier - remainder);
4227
4228 return num;
4229}
4230
Aalique Grahame22e49102018-12-18 14:23:57 -08004231static size_t get_stream_buffer_size(size_t duration_ms,
4232 uint32_t sample_rate,
4233 audio_format_t format,
4234 int channel_count,
4235 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236{
4237 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004238 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004239
Aalique Grahame22e49102018-12-18 14:23:57 -08004240 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004241 if (is_low_latency)
4242 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304243
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004244 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004245 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246
Ralf Herzbd08d632018-09-28 15:50:49 +02004247 /* make sure the size is multiple of 32 bytes and additionally multiple of
4248 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004249 * At 48 kHz mono 16-bit PCM:
4250 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4251 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004252 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004253 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004254 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004255
4256 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257}
4258
Aalique Grahame22e49102018-12-18 14:23:57 -08004259static size_t get_input_buffer_size(uint32_t sample_rate,
4260 audio_format_t format,
4261 int channel_count,
4262 bool is_low_latency)
4263{
4264 /* Don't know if USB HIFI in this context so use true to be conservative */
4265 if (check_input_parameters(sample_rate, format, channel_count,
4266 true /*is_usb_hifi */) != 0)
4267 return 0;
4268
4269 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4270 sample_rate,
4271 format,
4272 channel_count,
4273 is_low_latency);
4274}
4275
Derek Chenf6318be2017-06-12 17:16:24 -04004276size_t get_output_period_size(uint32_t sample_rate,
4277 audio_format_t format,
4278 int channel_count,
4279 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304280{
4281 size_t size = 0;
4282 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4283
4284 if ((duration == 0) || (sample_rate == 0) ||
4285 (bytes_per_sample == 0) || (channel_count == 0)) {
4286 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4287 bytes_per_sample, channel_count);
4288 return -EINVAL;
4289 }
4290
4291 size = (sample_rate *
4292 duration *
4293 bytes_per_sample *
4294 channel_count) / 1000;
4295 /*
4296 * To have same PCM samples for all channels, the buffer size requires to
4297 * be multiple of (number of channels * bytes per sample)
4298 * For writes to succeed, the buffer must be written at address which is multiple of 32
4299 */
4300 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4301
4302 return (size/(channel_count * bytes_per_sample));
4303}
4304
Zhou Song48453a02018-01-10 17:50:59 +08004305static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304306{
4307 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004308 uint64_t written_frames = 0;
4309 uint64_t kernel_frames = 0;
4310 uint64_t dsp_frames = 0;
4311 uint64_t signed_frames = 0;
4312 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304313
4314 /* This adjustment accounts for buffering after app processor.
4315 * It is based on estimated DSP latency per use case, rather than exact.
4316 */
Robert Lee58215542019-07-15 20:55:12 +08004317 pthread_mutex_lock(&adev->lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004318 dsp_frames = platform_render_latency(out->dev, out->usecase) *
4319 out->sample_rate / 1000000LL;
Robert Lee58215542019-07-15 20:55:12 +08004320 pthread_mutex_unlock(&adev->lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304321
Zhou Song48453a02018-01-10 17:50:59 +08004322 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004323 written_frames = out->written /
4324 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4325
Ashish Jain5106d362016-05-11 19:23:33 +05304326 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4327 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4328 * hence only estimate.
4329 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004330 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4331 kernel_frames = kernel_buffer_size /
4332 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304333
Weiyin Jiang4813da12020-05-28 00:37:28 +08004334 if (written_frames >= (kernel_frames + dsp_frames))
4335 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304336
Zhou Song48453a02018-01-10 17:50:59 +08004337 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304338 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004339 if (timestamp != NULL )
4340 *timestamp = out->writeAt;
4341 } else if (timestamp != NULL) {
4342 clock_gettime(CLOCK_MONOTONIC, timestamp);
4343 }
4344 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304345
Weiyin Jiang4813da12020-05-28 00:37:28 +08004346 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4347 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304348
4349 return actual_frames_rendered;
4350}
4351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4353{
4354 struct stream_out *out = (struct stream_out *)stream;
4355
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004356 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004357}
4358
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004359static int out_set_sample_rate(struct audio_stream *stream __unused,
4360 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361{
4362 return -ENOSYS;
4363}
4364
4365static size_t out_get_buffer_size(const struct audio_stream *stream)
4366{
4367 struct stream_out *out = (struct stream_out *)stream;
4368
Varun Balaraje49253e2017-07-06 19:48:56 +05304369 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304370 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304371 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304372 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4373 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4374 else
4375 return out->compr_config.fragment_size;
4376 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004377 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304378 else if (is_offload_usecase(out->usecase) &&
4379 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304380 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004381
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004382 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004383 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004384}
4385
4386static uint32_t out_get_channels(const struct audio_stream *stream)
4387{
4388 struct stream_out *out = (struct stream_out *)stream;
4389
4390 return out->channel_mask;
4391}
4392
4393static audio_format_t out_get_format(const struct audio_stream *stream)
4394{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004395 struct stream_out *out = (struct stream_out *)stream;
4396
4397 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004398}
4399
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004400static int out_set_format(struct audio_stream *stream __unused,
4401 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004402{
4403 return -ENOSYS;
4404}
4405
4406static int out_standby(struct audio_stream *stream)
4407{
4408 struct stream_out *out = (struct stream_out *)stream;
4409 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004410 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004411
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304412 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4413 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004414
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004415 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004416 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004417 if (adev->adm_deregister_stream)
4418 adev->adm_deregister_stream(adev->adm_data, out->handle);
4419
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004420 if (is_offload_usecase(out->usecase))
4421 stop_compressed_output_l(out);
4422
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004423 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004424 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004425 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4426 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304427 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004428 pthread_mutex_unlock(&adev->lock);
4429 pthread_mutex_unlock(&out->lock);
4430 ALOGD("VOIP output entered standby");
4431 return 0;
4432 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004433 if (out->pcm) {
4434 pcm_close(out->pcm);
4435 out->pcm = NULL;
4436 }
Meng Wanga09da002020-04-20 12:56:04 +08004437 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4438 if (adev->haptic_pcm) {
4439 pcm_close(adev->haptic_pcm);
4440 adev->haptic_pcm = NULL;
4441 }
4442
4443 if (adev->haptic_buffer != NULL) {
4444 free(adev->haptic_buffer);
4445 adev->haptic_buffer = NULL;
4446 adev->haptic_buffer_size = 0;
4447 }
4448 adev->haptic_pcm_device_id = 0;
4449 }
4450
Haynes Mathew George16081042017-05-31 17:16:49 -07004451 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4452 do_stop = out->playback_started;
4453 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004454
4455 if (out->mmap_shared_memory_fd >= 0) {
4456 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4457 __func__, out->mmap_shared_memory_fd);
4458 close(out->mmap_shared_memory_fd);
4459 out->mmap_shared_memory_fd = -1;
4460 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004461 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004462 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004463 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304464 out->send_next_track_params = false;
4465 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004466 out->gapless_mdata.encoder_delay = 0;
4467 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004468 if (out->compr != NULL) {
4469 compress_close(out->compr);
4470 out->compr = NULL;
4471 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004472 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004473 if (do_stop) {
4474 stop_output_stream(out);
4475 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304476 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004477 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004478 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004479 }
4480 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304481 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004482 return 0;
4483}
4484
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304485static int out_on_error(struct audio_stream *stream)
4486{
4487 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004488 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304489
4490 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004491 // always send CMD_ERROR for offload streams, this
4492 // is needed e.g. when SSR happens within compress_open
4493 // since the stream is active, offload_callback_thread is also active.
4494 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4495 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004496 }
4497 pthread_mutex_unlock(&out->lock);
4498
4499 status = out_standby(&out->stream.common);
4500
4501 lock_output_stream(out);
4502 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004503 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304504 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304505
4506 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4507 ALOGD("Setting previous card status if offline");
4508 out->prev_card_status_offline = true;
4509 }
4510
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304511 pthread_mutex_unlock(&out->lock);
4512
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004513 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304514}
4515
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304516/*
4517 *standby implementation without locks, assumes that the callee already
4518 *has taken adev and out lock.
4519 */
4520int out_standby_l(struct audio_stream *stream)
4521{
4522 struct stream_out *out = (struct stream_out *)stream;
4523 struct audio_device *adev = out->dev;
4524
4525 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4526 stream, out->usecase, use_case_table[out->usecase]);
4527
4528 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004529 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304530 if (adev->adm_deregister_stream)
4531 adev->adm_deregister_stream(adev->adm_data, out->handle);
4532
4533 if (is_offload_usecase(out->usecase))
4534 stop_compressed_output_l(out);
4535
4536 out->standby = true;
4537 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4538 voice_extn_compress_voip_close_output_stream(stream);
4539 out->started = 0;
4540 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004541 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304542 return 0;
4543 } else if (!is_offload_usecase(out->usecase)) {
4544 if (out->pcm) {
4545 pcm_close(out->pcm);
4546 out->pcm = NULL;
4547 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004548 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4549 if (adev->haptic_pcm) {
4550 pcm_close(adev->haptic_pcm);
4551 adev->haptic_pcm = NULL;
4552 }
4553
4554 if (adev->haptic_buffer != NULL) {
4555 free(adev->haptic_buffer);
4556 adev->haptic_buffer = NULL;
4557 adev->haptic_buffer_size = 0;
4558 }
4559 adev->haptic_pcm_device_id = 0;
4560 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304561 } else {
4562 ALOGD("copl(%p):standby", out);
4563 out->send_next_track_params = false;
4564 out->is_compr_metadata_avail = false;
4565 out->gapless_mdata.encoder_delay = 0;
4566 out->gapless_mdata.encoder_padding = 0;
4567 if (out->compr != NULL) {
4568 compress_close(out->compr);
4569 out->compr = NULL;
4570 }
4571 }
4572 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004573 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304574 }
4575 ALOGD("%s: exit", __func__);
4576 return 0;
4577}
4578
Aalique Grahame22e49102018-12-18 14:23:57 -08004579static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004580{
Aalique Grahame22e49102018-12-18 14:23:57 -08004581 struct stream_out *out = (struct stream_out *)stream;
4582
4583 // We try to get the lock for consistency,
4584 // but it isn't necessary for these variables.
4585 // If we're not in standby, we may be blocked on a write.
4586 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4587 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4588 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4589
Andy Hunga1f48fa2019-07-01 18:14:53 -07004590 char buffer[256]; // for statistics formatting
4591 if (!is_offload_usecase(out->usecase)) {
4592 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4593 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4594 }
4595
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004596 if (out->start_latency_ms.n > 0) {
4597 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4598 dprintf(fd, " Start latency ms: %s\n", buffer);
4599 }
4600
Aalique Grahame22e49102018-12-18 14:23:57 -08004601 if (locked) {
4602 pthread_mutex_unlock(&out->lock);
4603 }
4604
4605 // dump error info
4606 (void)error_log_dump(
4607 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004609 return 0;
4610}
4611
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004612static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4613{
4614 int ret = 0;
4615 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004616
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004617 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004618 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004619 return -EINVAL;
4620 }
4621
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304622 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004623
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004624 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4625 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304626 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004627 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004628 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4629 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304630 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004631 }
4632
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004633 ALOGV("%s new encoder delay %u and padding %u", __func__,
4634 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4635
4636 return 0;
4637}
4638
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004639static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4640{
4641 return out == adev->primary_output || out == adev->voice_tx_output;
4642}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004643
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304644// note: this call is safe only if the stream_cb is
4645// removed first in close_output_stream (as is done now).
4646static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4647{
4648 if (!stream || !parms)
4649 return;
4650
4651 struct stream_out *out = (struct stream_out *)stream;
4652 struct audio_device *adev = out->dev;
4653
4654 card_status_t status;
4655 int card;
4656 if (parse_snd_card_status(parms, &card, &status) < 0)
4657 return;
4658
4659 pthread_mutex_lock(&adev->lock);
4660 bool valid_cb = (card == adev->snd_card);
4661 pthread_mutex_unlock(&adev->lock);
4662
4663 if (!valid_cb)
4664 return;
4665
4666 lock_output_stream(out);
4667 if (out->card_status != status)
4668 out->card_status = status;
4669 pthread_mutex_unlock(&out->lock);
4670
4671 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4672 use_case_table[out->usecase],
4673 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4674
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304675 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304676 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304677 if (voice_is_call_state_active(adev) &&
4678 out == adev->primary_output) {
4679 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4680 pthread_mutex_lock(&adev->lock);
4681 voice_stop_call(adev);
4682 adev->mode = AUDIO_MODE_NORMAL;
4683 pthread_mutex_unlock(&adev->lock);
4684 }
4685 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304686 return;
4687}
4688
Kevin Rocardfce19002017-08-07 19:21:36 -07004689static int get_alive_usb_card(struct str_parms* parms) {
4690 int card;
4691 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4692 !audio_extn_usb_alive(card)) {
4693 return card;
4694 }
4695 return -ENODEV;
4696}
4697
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004698int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004699 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004700{
4701 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004702 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004703 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004704 bool bypass_a2dp = false;
4705 bool reconfig = false;
4706 unsigned long service_interval = 0;
4707
4708 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004709 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4710
4711 list_init(&new_devices);
4712 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004713
4714 lock_output_stream(out);
4715 pthread_mutex_lock(&adev->lock);
4716
4717 /*
4718 * When HDMI cable is unplugged the music playback is paused and
4719 * the policy manager sends routing=0. But the audioflinger continues
4720 * to write data until standby time (3sec). As the HDMI core is
4721 * turned off, the write gets blocked.
4722 * Avoid this by routing audio to speaker until standby.
4723 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004724 if (is_single_device_type_equal(&out->device_list,
4725 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004726 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004727 !audio_extn_passthru_is_passthrough_stream(out) &&
4728 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004729 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004730 }
4731 /*
4732 * When A2DP is disconnected the
4733 * music playback is paused and the policy manager sends routing=0
4734 * But the audioflinger continues to write data until standby time
4735 * (3sec). As BT is turned off, the write gets blocked.
4736 * Avoid this by routing audio to speaker until standby.
4737 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004738 if (is_a2dp_out_device_type(&out->device_list) &&
4739 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004740 !audio_extn_a2dp_source_is_ready() &&
4741 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004742 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004743 }
4744 /*
4745 * When USB headset is disconnected the music platback paused
4746 * and the policy manager send routing=0. But if the USB is connected
4747 * back before the standby time, AFE is not closed and opened
4748 * when USB is connected back. So routing to speker will guarantee
4749 * AFE reconfiguration and AFE will be opend once USB is connected again
4750 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004751 if (is_usb_out_device_type(&out->device_list) &&
4752 list_empty(&new_devices) &&
4753 !audio_extn_usb_connected(NULL)) {
4754 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4755 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004756 /* To avoid a2dp to sco overlapping / BT device improper state
4757 * check with BT lib about a2dp streaming support before routing
4758 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004759 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004760 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004761 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4762 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004763 //combo usecase just by pass a2dp
4764 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4765 bypass_a2dp = true;
4766 } else {
4767 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4768 /* update device to a2dp and don't route as BT returned error
4769 * However it is still possible a2dp routing called because
4770 * of current active device disconnection (like wired headset)
4771 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004772 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004773 pthread_mutex_unlock(&adev->lock);
4774 pthread_mutex_unlock(&out->lock);
4775 goto error;
4776 }
4777 }
4778 }
4779
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004780 // Workaround: If routing to an non existing usb device, fail gracefully
4781 // The routing request will otherwise block during 10 second
4782 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004783 if (is_usb_out_device_type(&new_devices)) {
4784 struct str_parms *parms =
4785 str_parms_create_str(get_usb_device_address(&new_devices));
4786 if (!parms)
4787 goto error;
4788 if ((card = get_alive_usb_card(parms)) >= 0) {
4789 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4790 pthread_mutex_unlock(&adev->lock);
4791 pthread_mutex_unlock(&out->lock);
4792 str_parms_destroy(parms);
4793 ret = -ENOSYS;
4794 goto error;
4795 }
4796 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004797 }
4798
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004799 // Workaround: If routing to an non existing hdmi device, fail gracefully
4800 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4801 (platform_get_edid_info_v2(adev->platform,
4802 out->extconn.cs.controller,
4803 out->extconn.cs.stream) != 0)) {
4804 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4805 pthread_mutex_unlock(&adev->lock);
4806 pthread_mutex_unlock(&out->lock);
4807 ret = -ENOSYS;
4808 goto error;
4809 }
4810
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004811 /*
4812 * select_devices() call below switches all the usecases on the same
4813 * backend to the new device. Refer to check_usecases_codec_backend() in
4814 * the select_devices(). But how do we undo this?
4815 *
4816 * For example, music playback is active on headset (deep-buffer usecase)
4817 * and if we go to ringtones and select a ringtone, low-latency usecase
4818 * will be started on headset+speaker. As we can't enable headset+speaker
4819 * and headset devices at the same time, select_devices() switches the music
4820 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4821 * So when the ringtone playback is completed, how do we undo the same?
4822 *
4823 * We are relying on the out_set_parameters() call on deep-buffer output,
4824 * once the ringtone playback is ended.
4825 * NOTE: We should not check if the current devices are same as new devices.
4826 * Because select_devices() must be called to switch back the music
4827 * playback to headset.
4828 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004829 if (!list_empty(&new_devices)) {
4830 bool same_dev = compare_devices(&out->device_list, &new_devices);
4831 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004832
4833 if (output_drives_call(adev, out)) {
4834 if (!voice_is_call_state_active(adev)) {
4835 if (adev->mode == AUDIO_MODE_IN_CALL) {
4836 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004837 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004838 service_interval =
4839 audio_extn_usb_find_service_interval(true, true /*playback*/);
4840 audio_extn_usb_set_service_interval(true /*playback*/,
4841 service_interval,
4842 &reconfig);
4843 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4844 }
4845 ret = voice_start_call(adev);
4846 }
4847 } else {
4848 adev->current_call_output = out;
4849 voice_update_devices_for_all_voice_usecases(adev);
4850 }
4851 }
4852
4853 if (!out->standby) {
4854 if (!same_dev) {
4855 ALOGV("update routing change");
4856 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4857 adev->perf_lock_opts,
4858 adev->perf_lock_opts_size);
4859 if (adev->adm_on_routing_change)
4860 adev->adm_on_routing_change(adev->adm_data,
4861 out->handle);
4862 }
4863 if (!bypass_a2dp) {
4864 select_devices(adev, out->usecase);
4865 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004866 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4867 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004868 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004869 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004870 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004871 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004872 }
4873
4874 if (!same_dev) {
4875 // on device switch force swap, lower functions will make sure
4876 // to check if swap is allowed or not.
4877 platform_set_swap_channels(adev, true);
4878 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4879 }
4880 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4881 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004882 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004883 pthread_mutex_lock(&out->compr_mute_lock);
4884 out->a2dp_compress_mute = false;
4885 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4886 pthread_mutex_unlock(&out->compr_mute_lock);
4887 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4888 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4889 }
4890 }
4891 }
4892
4893 pthread_mutex_unlock(&adev->lock);
4894 pthread_mutex_unlock(&out->lock);
4895
4896 /*handles device and call state changes*/
4897 audio_extn_extspk_update(adev->extspk);
4898
4899error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004900 ALOGV("%s: exit: code(%d)", __func__, ret);
4901 return ret;
4902}
4903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004904static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4905{
4906 struct stream_out *out = (struct stream_out *)stream;
4907 struct audio_device *adev = out->dev;
4908 struct str_parms *parms;
4909 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004910 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004911 int ext_controller = -1;
4912 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004913
sangwoobc677242013-08-08 16:53:43 +09004914 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004915 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004916 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304917 if (!parms)
4918 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004919
4920 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4921 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08004922 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004923 out->extconn.cs.controller = ext_controller;
4924 out->extconn.cs.stream = ext_stream;
4925 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4926 use_case_table[out->usecase], out->extconn.cs.controller,
4927 out->extconn.cs.stream);
4928 }
4929
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004930 if (out == adev->primary_output) {
4931 pthread_mutex_lock(&adev->lock);
4932 audio_extn_set_parameters(adev, parms);
4933 pthread_mutex_unlock(&adev->lock);
4934 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004935 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004936 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004937 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004938
4939 audio_extn_dts_create_state_notifier_node(out->usecase);
4940 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4941 popcount(out->channel_mask),
4942 out->playback_started);
4943
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004944 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004945 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004946
Surendar Karkaf51b5842018-04-26 11:28:38 +05304947 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4948 sizeof(value));
4949 if (err >= 0) {
4950 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4951 audio_extn_send_dual_mono_mixing_coefficients(out);
4952 }
4953
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304954 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4955 if (err >= 0) {
4956 strlcpy(out->profile, value, sizeof(out->profile));
4957 ALOGV("updating stream profile with value '%s'", out->profile);
4958 lock_output_stream(out);
4959 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4960 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004961 &out->device_list, out->flags,
4962 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304963 out->sample_rate, out->bit_width,
4964 out->channel_mask, out->profile,
4965 &out->app_type_cfg);
4966 pthread_mutex_unlock(&out->lock);
4967 }
4968
Alexy Joseph98988832017-01-13 14:56:59 -08004969 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004970 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4971 // and vendor.audio.hal.output.suspend.supported is set to true
4972 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004973 //check suspend parameter only for low latency and if the property
4974 //is enabled
4975 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4976 ALOGI("%s: got suspend_playback %s", __func__, value);
4977 lock_output_stream(out);
4978 if (!strncmp(value, "false", 5)) {
4979 //suspend_playback=false is supposed to set QOS value back to 75%
4980 //the mixer control sent with value Enable will achieve that
4981 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4982 } else if (!strncmp (value, "true", 4)) {
4983 //suspend_playback=true is supposed to remove QOS value
4984 //resetting the mixer control will set the default value
4985 //for the mixer control which is Disable and this removes the QOS vote
4986 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4987 } else {
4988 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4989 " got %s", __func__, value);
4990 ret = -1;
4991 }
4992
4993 if (ret != 0) {
4994 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4995 __func__, out->pm_qos_mixer_path, ret);
4996 }
4997
4998 pthread_mutex_unlock(&out->lock);
4999 }
5000 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005001
Alexy Joseph98988832017-01-13 14:56:59 -08005002 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005003 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305004error:
Eric Laurent994a6932013-07-17 11:51:42 -07005005 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005006 return ret;
5007}
5008
Paul McLeana50b7332018-12-17 08:24:21 -07005009static int in_set_microphone_direction(const struct audio_stream_in *stream,
5010 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005011 struct stream_in *in = (struct stream_in *)stream;
5012
5013 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5014
5015 in->direction = dir;
5016
5017 if (in->standby)
5018 return 0;
5019
5020 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005021}
5022
5023static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005024 struct stream_in *in = (struct stream_in *)stream;
5025
5026 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5027
5028 if (zoom > 1.0 || zoom < -1.0)
5029 return -EINVAL;
5030
5031 in->zoom = zoom;
5032
5033 if (in->standby)
5034 return 0;
5035
5036 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005037}
5038
5039
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005040static bool stream_get_parameter_channels(struct str_parms *query,
5041 struct str_parms *reply,
5042 audio_channel_mask_t *supported_channel_masks) {
5043 int ret = -1;
5044 char value[512];
5045 bool first = true;
5046 size_t i, j;
5047
5048 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5049 ret = 0;
5050 value[0] = '\0';
5051 i = 0;
5052 while (supported_channel_masks[i] != 0) {
5053 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5054 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5055 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305056 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005057
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305058 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005059 first = false;
5060 break;
5061 }
5062 }
5063 i++;
5064 }
5065 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5066 }
5067 return ret == 0;
5068}
5069
5070static bool stream_get_parameter_formats(struct str_parms *query,
5071 struct str_parms *reply,
5072 audio_format_t *supported_formats) {
5073 int ret = -1;
5074 char value[256];
5075 size_t i, j;
5076 bool first = true;
5077
5078 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5079 ret = 0;
5080 value[0] = '\0';
5081 i = 0;
5082 while (supported_formats[i] != 0) {
5083 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5084 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5085 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305086 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005087 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305088 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005089 first = false;
5090 break;
5091 }
5092 }
5093 i++;
5094 }
5095 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5096 }
5097 return ret == 0;
5098}
5099
5100static bool stream_get_parameter_rates(struct str_parms *query,
5101 struct str_parms *reply,
5102 uint32_t *supported_sample_rates) {
5103
5104 int i;
5105 char value[256];
5106 int ret = -1;
5107 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5108 ret = 0;
5109 value[0] = '\0';
5110 i=0;
5111 int cursor = 0;
5112 while (supported_sample_rates[i]) {
5113 int avail = sizeof(value) - cursor;
5114 ret = snprintf(value + cursor, avail, "%s%d",
5115 cursor > 0 ? "|" : "",
5116 supported_sample_rates[i]);
5117 if (ret < 0 || ret >= avail) {
5118 // if cursor is at the last element of the array
5119 // overwrite with \0 is duplicate work as
5120 // snprintf already put a \0 in place.
5121 // else
5122 // we had space to write the '|' at value[cursor]
5123 // (which will be overwritten) or no space to fill
5124 // the first element (=> cursor == 0)
5125 value[cursor] = '\0';
5126 break;
5127 }
5128 cursor += ret;
5129 ++i;
5130 }
5131 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5132 value);
5133 }
5134 return ret >= 0;
5135}
5136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005137static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5138{
5139 struct stream_out *out = (struct stream_out *)stream;
5140 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005141 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005142 char value[256];
5143 struct str_parms *reply = str_parms_create();
5144 size_t i, j;
5145 int ret;
5146 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005147
5148 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005149 if (reply) {
5150 str_parms_destroy(reply);
5151 }
5152 if (query) {
5153 str_parms_destroy(query);
5154 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005155 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5156 return NULL;
5157 }
5158
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005159 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005160 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5161 if (ret >= 0) {
5162 value[0] = '\0';
5163 i = 0;
5164 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005165 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5166 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005167 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005168 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005169 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005170 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005171 first = false;
5172 break;
5173 }
5174 }
5175 i++;
5176 }
5177 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5178 str = str_parms_to_str(reply);
5179 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005180 voice_extn_out_get_parameters(out, query, reply);
5181 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005182 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005183
Alexy Joseph62142aa2015-11-16 15:10:34 -08005184
5185 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5186 if (ret >= 0) {
5187 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305188 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5189 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005190 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305191 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005192 } else {
5193 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305194 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005195 }
5196 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005197 if (str)
5198 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005199 str = str_parms_to_str(reply);
5200 }
5201
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005202 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5203 if (ret >= 0) {
5204 value[0] = '\0';
5205 i = 0;
5206 first = true;
5207 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005208 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5209 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005210 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005211 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005212 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005213 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005214 first = false;
5215 break;
5216 }
5217 }
5218 i++;
5219 }
5220 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005221 if (str)
5222 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005223 str = str_parms_to_str(reply);
5224 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005225
5226 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5227 if (ret >= 0) {
5228 value[0] = '\0';
5229 i = 0;
5230 first = true;
5231 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005232 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5233 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005234 if (!first) {
5235 strlcat(value, "|", sizeof(value));
5236 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005237 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005238 first = false;
5239 break;
5240 }
5241 }
5242 i++;
5243 }
5244 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5245 if (str)
5246 free(str);
5247 str = str_parms_to_str(reply);
5248 }
5249
Alexy Joseph98988832017-01-13 14:56:59 -08005250 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5251 //only low latency track supports suspend_resume
5252 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005253 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005254 if (str)
5255 free(str);
5256 str = str_parms_to_str(reply);
5257 }
5258
5259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005260 str_parms_destroy(query);
5261 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005262 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005263 return str;
5264}
5265
5266static uint32_t out_get_latency(const struct audio_stream_out *stream)
5267{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005268 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005269 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005270 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005271
Alexy Josephaa54c872014-12-03 02:46:47 -08005272 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305273 lock_output_stream(out);
5274 latency = audio_extn_utils_compress_get_dsp_latency(out);
5275 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005276 } else if ((out->realtime) ||
5277 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005278 // since the buffer won't be filled up faster than realtime,
5279 // return a smaller number
5280 if (out->config.rate)
5281 period_ms = (out->af_period_multiplier * out->config.period_size *
5282 1000) / (out->config.rate);
5283 else
5284 period_ms = 0;
Robert Lee58215542019-07-15 20:55:12 +08005285 pthread_mutex_lock(&adev->lock);
5286 latency = period_ms + platform_render_latency(out->dev, out->usecase)/1000;
5287 pthread_mutex_unlock(&adev->lock);
Alexy Josephaa54c872014-12-03 02:46:47 -08005288 } else {
5289 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005290 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005291 }
5292
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005293 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005294 latency += audio_extn_a2dp_get_encoder_latency();
5295
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305296 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005297 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005298}
5299
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305300static float AmpToDb(float amplification)
5301{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305302 float db = DSD_VOLUME_MIN_DB;
5303 if (amplification > 0) {
5304 db = 20 * log10(amplification);
5305 if(db < DSD_VOLUME_MIN_DB)
5306 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305307 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305308 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305309}
5310
Arun Mirpuri5d170872019-03-26 13:21:31 -07005311static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5312 float right)
5313{
5314 struct stream_out *out = (struct stream_out *)stream;
5315 long volume = 0;
5316 char mixer_ctl_name[128] = "";
5317 struct audio_device *adev = out->dev;
5318 struct mixer_ctl *ctl = NULL;
5319 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5320 PCM_PLAYBACK);
5321
5322 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5323 "Playback %d Volume", pcm_device_id);
5324 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5325 if (!ctl) {
5326 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5327 __func__, mixer_ctl_name);
5328 return -EINVAL;
5329 }
5330 if (left != right)
5331 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5332 __func__, left, right);
5333 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5334 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5335 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5336 __func__, mixer_ctl_name, volume);
5337 return -EINVAL;
5338 }
5339 return 0;
5340}
5341
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305342static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5343 float right)
5344{
5345 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305346 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305347 char mixer_ctl_name[128];
5348 struct audio_device *adev = out->dev;
5349 struct mixer_ctl *ctl;
5350 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5351 PCM_PLAYBACK);
5352
5353 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5354 "Compress Playback %d Volume", pcm_device_id);
5355 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5356 if (!ctl) {
5357 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5358 __func__, mixer_ctl_name);
5359 return -EINVAL;
5360 }
5361 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5362 __func__, mixer_ctl_name, left, right);
5363 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5364 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5365 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5366
5367 return 0;
5368}
5369
Zhou Song2b8f28f2017-09-11 10:51:38 +08005370static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5371 float right)
5372{
5373 struct stream_out *out = (struct stream_out *)stream;
5374 char mixer_ctl_name[] = "App Type Gain";
5375 struct audio_device *adev = out->dev;
5376 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305377 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005378
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005379 if (!is_valid_volume(left, right)) {
5380 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5381 __func__, left, right);
5382 return -EINVAL;
5383 }
5384
Zhou Song2b8f28f2017-09-11 10:51:38 +08005385 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5386 if (!ctl) {
5387 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5388 __func__, mixer_ctl_name);
5389 return -EINVAL;
5390 }
5391
5392 set_values[0] = 0; //0: Rx Session 1:Tx Session
5393 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305394 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5395 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005396
5397 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5398 return 0;
5399}
5400
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305401static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5402 float right)
5403{
5404 struct stream_out *out = (struct stream_out *)stream;
5405 /* Volume control for pcm playback */
5406 if (left != right) {
5407 return -EINVAL;
5408 } else {
5409 char mixer_ctl_name[128];
5410 struct audio_device *adev = out->dev;
5411 struct mixer_ctl *ctl;
5412 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5413 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5414 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5415 if (!ctl) {
5416 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5417 return -EINVAL;
5418 }
5419
5420 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5421 int ret = mixer_ctl_set_value(ctl, 0, volume);
5422 if (ret < 0) {
5423 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5424 return -EINVAL;
5425 }
5426
5427 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5428
5429 return 0;
5430 }
5431}
5432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005433static int out_set_volume(struct audio_stream_out *stream, float left,
5434 float right)
5435{
Eric Laurenta9024de2013-04-04 09:19:12 -07005436 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005437 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305438 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005439
Arun Mirpuri5d170872019-03-26 13:21:31 -07005440 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005441 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5442 /* only take left channel into account: the API is for stereo anyway */
5443 out->muted = (left == 0.0f);
5444 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005445 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305446 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005447 /*
5448 * Set mute or umute on HDMI passthrough stream.
5449 * Only take left channel into account.
5450 * Mute is 0 and unmute 1
5451 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305452 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305453 } else if (out->format == AUDIO_FORMAT_DSD){
5454 char mixer_ctl_name[128] = "DSD Volume";
5455 struct audio_device *adev = out->dev;
5456 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5457
5458 if (!ctl) {
5459 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5460 __func__, mixer_ctl_name);
5461 return -EINVAL;
5462 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305463 volume[0] = (long)(AmpToDb(left));
5464 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305465 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5466 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005467 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005468 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005469 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5470 struct listnode *node = NULL;
5471 list_for_each(node, &adev->active_outputs_list) {
5472 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5473 streams_output_ctxt_t,
5474 list);
5475 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5476 out->volume_l = out_ctxt->output->volume_l;
5477 out->volume_r = out_ctxt->output->volume_r;
5478 }
5479 }
5480 if (!out->a2dp_compress_mute) {
5481 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5482 }
5483 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005484 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305485 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005486 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305487 if (!out->a2dp_compress_mute)
5488 ret = out_set_compr_volume(stream, left, right);
5489 out->volume_l = left;
5490 out->volume_r = right;
5491 pthread_mutex_unlock(&out->compr_mute_lock);
5492 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005493 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005494 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005495 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5496 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5497 if (!out->standby) {
5498 audio_extn_utils_send_app_type_gain(out->dev,
5499 out->app_type_cfg.app_type,
5500 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005501 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005502 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005503 out->volume_l = left;
5504 out->volume_r = right;
5505 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005506 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5507 ALOGV("%s: MMAP set volume called", __func__);
5508 if (!out->standby)
5509 ret = out_set_mmap_volume(stream, left, right);
5510 out->volume_l = left;
5511 out->volume_r = right;
5512 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305513 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305514 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5515 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305516 /* Volume control for pcm playback */
5517 if (!out->standby)
5518 ret = out_set_pcm_volume(stream, left, right);
5519 else
5520 out->apply_volume = true;
5521
5522 out->volume_l = left;
5523 out->volume_r = right;
5524 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005525 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5526 ALOGV("%s: bus device set volume called", __func__);
5527 if (!out->standby)
5528 ret = out_set_pcm_volume(stream, left, right);
5529 out->volume_l = left;
5530 out->volume_r = right;
5531 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005532 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005534 return -ENOSYS;
5535}
5536
Zhou Songc9672822017-08-16 16:01:39 +08005537static void update_frames_written(struct stream_out *out, size_t bytes)
5538{
5539 size_t bpf = 0;
5540
5541 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5542 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5543 bpf = 1;
5544 else if (!is_offload_usecase(out->usecase))
5545 bpf = audio_bytes_per_sample(out->format) *
5546 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005547
5548 pthread_mutex_lock(&out->position_query_lock);
5549 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005550 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005551 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5552 }
5553 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005554}
5555
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005556int split_and_write_audio_haptic_data(struct stream_out *out,
5557 const void *buffer, size_t bytes_to_write)
5558{
5559 struct audio_device *adev = out->dev;
5560
5561 int ret = 0;
5562 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5563 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5564 size_t frame_size = channel_count * bytes_per_sample;
5565 size_t frame_count = bytes_to_write / frame_size;
5566
5567 bool force_haptic_path =
5568 property_get_bool("vendor.audio.test_haptic", false);
5569
5570 // extract Haptics data from Audio buffer
5571 bool alloc_haptic_buffer = false;
5572 int haptic_channel_count = adev->haptics_config.channels;
5573 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5574 size_t audio_frame_size = frame_size - haptic_frame_size;
5575 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5576
5577 if (adev->haptic_buffer == NULL) {
5578 alloc_haptic_buffer = true;
5579 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5580 free(adev->haptic_buffer);
5581 adev->haptic_buffer_size = 0;
5582 alloc_haptic_buffer = true;
5583 }
5584
5585 if (alloc_haptic_buffer) {
5586 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005587 if(adev->haptic_buffer == NULL) {
5588 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5589 return -ENOMEM;
5590 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005591 adev->haptic_buffer_size = total_haptic_buffer_size;
5592 }
5593
5594 size_t src_index = 0, aud_index = 0, hap_index = 0;
5595 uint8_t *audio_buffer = (uint8_t *)buffer;
5596 uint8_t *haptic_buffer = adev->haptic_buffer;
5597
5598 // This is required for testing only. This works for stereo data only.
5599 // One channel is fed to audio stream and other to haptic stream for testing.
5600 if (force_haptic_path)
5601 audio_frame_size = haptic_frame_size = bytes_per_sample;
5602
5603 for (size_t i = 0; i < frame_count; i++) {
5604 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5605 audio_frame_size);
5606 aud_index += audio_frame_size;
5607 src_index += audio_frame_size;
5608
5609 if (adev->haptic_pcm)
5610 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5611 haptic_frame_size);
5612 hap_index += haptic_frame_size;
5613 src_index += haptic_frame_size;
5614
5615 // This is required for testing only.
5616 // Discard haptic channel data.
5617 if (force_haptic_path)
5618 src_index += haptic_frame_size;
5619 }
5620
5621 // write to audio pipeline
5622 ret = pcm_write(out->pcm, (void *)audio_buffer,
5623 frame_count * audio_frame_size);
5624
5625 // write to haptics pipeline
5626 if (adev->haptic_pcm)
5627 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5628 frame_count * haptic_frame_size);
5629
5630 return ret;
5631}
5632
Aalique Grahame22e49102018-12-18 14:23:57 -08005633#ifdef NO_AUDIO_OUT
5634static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5635 const void *buffer __unused, size_t bytes)
5636{
5637 struct stream_out *out = (struct stream_out *)stream;
5638
5639 /* No Output device supported other than BT for playback.
5640 * Sleep for the amount of buffer duration
5641 */
5642 lock_output_stream(out);
5643 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5644 (const struct audio_stream_out *)&out->stream) /
5645 out_get_sample_rate(&out->stream.common));
5646 pthread_mutex_unlock(&out->lock);
5647 return bytes;
5648}
5649#endif
5650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005651static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5652 size_t bytes)
5653{
5654 struct stream_out *out = (struct stream_out *)stream;
5655 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005656 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305657 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005658 const size_t frame_size = audio_stream_out_frame_size(stream);
5659 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305660 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005661 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005662
Haynes Mathew George380745d2017-10-04 15:27:45 -07005663 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005664 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305665
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305666 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005667
Dhananjay Kumarac341582017-02-23 23:42:25 +05305668 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305669 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305670 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5671 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005672 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305673 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305674 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305675 ALOGD(" %s: sound card is not active/SSR state", __func__);
5676 ret= -EIO;
5677 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305678 }
5679 }
5680
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305681 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305682 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305683 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305684 goto exit;
5685 }
5686
Haynes Mathew George16081042017-05-31 17:16:49 -07005687 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5688 ret = -EINVAL;
5689 goto exit;
5690 }
5691
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005692 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305693 !out->is_iec61937_info_available) {
5694
5695 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5696 out->is_iec61937_info_available = true;
5697 } else if (audio_extn_passthru_is_enabled()) {
5698 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305699 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305700
5701 if((out->format == AUDIO_FORMAT_DTS) ||
5702 (out->format == AUDIO_FORMAT_DTS_HD)) {
5703 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5704 buffer, bytes);
5705 if (ret) {
5706 if (ret != -ENOSYS) {
5707 out->is_iec61937_info_available = false;
5708 ALOGD("iec61937 transmission info not yet updated retry");
5709 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305710 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305711 /* if stream has started and after that there is
5712 * stream config change (iec transmission config)
5713 * then trigger select_device to update backend configuration.
5714 */
5715 out->stream_config_changed = true;
5716 pthread_mutex_lock(&adev->lock);
5717 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305718 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005719 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305720 ret = -EINVAL;
5721 goto exit;
5722 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305723 pthread_mutex_unlock(&adev->lock);
5724 out->stream_config_changed = false;
5725 out->is_iec61937_info_available = true;
5726 }
5727 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305728
Meng Wang4c32fb42020-01-16 17:57:11 +08005729#ifdef AUDIO_GKI_ENABLED
5730 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5731 compr_passthr = out->compr_config.codec->reserved[0];
5732#else
5733 compr_passthr = out->compr_config.codec->compr_passthr;
5734#endif
5735
Garmond Leung317cbf12017-09-13 16:20:50 -07005736 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005737 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305738 (out->is_iec61937_info_available == true)) {
5739 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5740 ret = -EINVAL;
5741 goto exit;
5742 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305743 }
5744 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305745
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005746 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005747 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005748 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5749 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305750 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305751 ret = -EIO;
5752 goto exit;
5753 }
5754 }
5755 }
5756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005757 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005758 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005759 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5760
Eric Laurent150dbfe2013-02-27 14:31:02 -08005761 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005762 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5763 ret = voice_extn_compress_voip_start_output_stream(out);
5764 else
5765 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005766 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005767 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005768 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005769 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005770 goto exit;
5771 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305772 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005773 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
vivek mehtab72d08d2016-04-29 03:16:47 -07005774 if (last_known_cal_step != -1) {
5775 ALOGD("%s: retry previous failed cal level set", __func__);
5776 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305777 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005778 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305779
5780 if ((out->is_iec61937_info_available == true) &&
5781 (audio_extn_passthru_is_passthrough_stream(out))&&
5782 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5783 ret = -EINVAL;
5784 goto exit;
5785 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305786 if (out->set_dual_mono)
5787 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005788
5789 // log startup time in ms.
5790 simple_stats_log(
5791 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005792 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005793
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005794 if (adev->is_channel_status_set == false &&
5795 compare_device_type(&out->device_list,
5796 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005797 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305798 adev->is_channel_status_set = true;
5799 }
5800
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305801 if ((adev->use_old_pspd_mix_ctrl == true) &&
5802 (out->pspd_coeff_sent == false)) {
5803 /*
5804 * Need to resend pspd coefficients after stream started for
5805 * older kernel version as it does not save the coefficients
5806 * and also stream has to be started for coeff to apply.
5807 */
5808 usecase = get_usecase_from_list(adev, out->usecase);
5809 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305810 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305811 out->pspd_coeff_sent = true;
5812 }
5813 }
5814
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005815 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005816 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005817 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005818 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005819 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5820 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305821 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5822 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005823 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305824 out->send_next_track_params = false;
5825 out->is_compr_metadata_avail = false;
5826 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005827 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305828 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305829 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005830
Ashish Jain83a6cc22016-06-28 14:34:17 +05305831 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305832 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305833 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305834 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005835 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305836 return -EINVAL;
5837 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305838 audio_format_t dst_format = out->hal_op_format;
5839 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305840
Dieter Luecking5d57def2018-09-07 14:23:37 +02005841 /* prevent division-by-zero */
5842 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5843 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5844 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5845 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305846 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005847 ATRACE_END();
5848 return -EINVAL;
5849 }
5850
Ashish Jainf1eaa582016-05-23 20:54:24 +05305851 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5852 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5853
Ashish Jain83a6cc22016-06-28 14:34:17 +05305854 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305855 dst_format,
5856 buffer,
5857 src_format,
5858 frames);
5859
Ashish Jain83a6cc22016-06-28 14:34:17 +05305860 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305861 bytes_to_write);
5862
5863 /*Convert written bytes in audio flinger format*/
5864 if (ret > 0)
5865 ret = ((ret * format_to_bitwidth_table[out->format]) /
5866 format_to_bitwidth_table[dst_format]);
5867 }
5868 } else
5869 ret = compress_write(out->compr, buffer, bytes);
5870
Zhou Songc9672822017-08-16 16:01:39 +08005871 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5872 update_frames_written(out, bytes);
5873
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305874 if (ret < 0)
5875 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005876 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305877 /*msg to cb thread only if non blocking write is enabled*/
5878 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305879 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005880 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305881 } else if (-ENETRESET == ret) {
5882 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305883 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305884 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305885 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005886 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305887 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005888 }
Ashish Jain5106d362016-05-11 19:23:33 +05305889
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305890 /* Call compr start only when non-zero bytes of data is there to be rendered */
5891 if (!out->playback_started && ret > 0) {
5892 int status = compress_start(out->compr);
5893 if (status < 0) {
5894 ret = status;
5895 ALOGE("%s: compr start failed with err %d", __func__, errno);
5896 goto exit;
5897 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005898 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005899 out->playback_started = 1;
5900 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005901
5902 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5903 popcount(out->channel_mask),
5904 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005905 }
5906 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005907 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005908 return ret;
5909 } else {
5910 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005911 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005912 if (out->muted)
5913 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005914 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5915 __func__, frames, frame_size, bytes_to_write);
5916
Aalique Grahame22e49102018-12-18 14:23:57 -08005917 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005918 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5919 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5920 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005921 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5922 int16_t *src = (int16_t *)buffer;
5923 int16_t *dst = (int16_t *)buffer;
5924
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005925 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005926 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005927 "out_write called for %s use case with wrong properties",
5928 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005929
5930 /*
5931 * FIXME: this can be removed once audio flinger mixer supports
5932 * mono output
5933 */
5934
5935 /*
5936 * Code below goes over each frame in the buffer and adds both
5937 * L and R samples and then divides by 2 to convert to mono
5938 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005939 if (channel_count == 2) {
5940 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5941 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5942 }
5943 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005944 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005945 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07005946
5947 // Note: since out_get_presentation_position() is called alternating with out_write()
5948 // by AudioFlinger, we can check underruns using the prior timestamp read.
5949 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
5950 if (out->last_fifo_valid) {
5951 // compute drain to see if there is an underrun.
5952 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
5953 const int64_t frames_by_time =
5954 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
5955 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
5956
5957 if (underrun > 0) {
5958 simple_stats_log(&out->fifo_underruns, underrun);
5959
5960 ALOGW("%s: underrun(%lld) "
5961 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
5962 __func__,
5963 (long long)out->fifo_underruns.n,
5964 (long long)frames_by_time,
5965 (long long)out->last_fifo_frames_remaining);
5966 }
5967 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
5968 }
5969
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305970 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005971
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005972 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005973
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005974 if (out->config.rate)
5975 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5976 out->config.rate;
5977
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005978 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005979 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5980
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005981 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005982 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005983 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305984 out->convert_buffer != NULL) {
5985
5986 memcpy_by_audio_format(out->convert_buffer,
5987 out->hal_op_format,
5988 buffer,
5989 out->hal_ip_format,
5990 out->config.period_size * out->config.channels);
5991
5992 ret = pcm_write(out->pcm, out->convert_buffer,
5993 (out->config.period_size *
5994 out->config.channels *
5995 format_to_bitwidth_table[out->hal_op_format]));
5996 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305997 /*
5998 * To avoid underrun in DSP when the application is not pumping
5999 * data at required rate, check for the no. of bytes and ignore
6000 * pcm_write if it is less than actual buffer size.
6001 * It is a work around to a change in compress VOIP driver.
6002 */
6003 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6004 bytes < (out->config.period_size * out->config.channels *
6005 audio_bytes_per_sample(out->format))) {
6006 size_t voip_buf_size =
6007 out->config.period_size * out->config.channels *
6008 audio_bytes_per_sample(out->format);
6009 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6010 __func__, bytes, voip_buf_size);
6011 usleep(((uint64_t)voip_buf_size - bytes) *
6012 1000000 / audio_stream_out_frame_size(stream) /
6013 out_get_sample_rate(&out->stream.common));
6014 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006015 } else {
6016 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6017 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6018 else
6019 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6020 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306021 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006022
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006023 release_out_focus(out);
6024
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306025 if (ret < 0)
6026 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006027 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306028 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006029 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006030 }
6031
6032exit:
Zhou Songc9672822017-08-16 16:01:39 +08006033 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306034 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306035 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306036 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006037 pthread_mutex_unlock(&out->lock);
6038
6039 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006040 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006041 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306042 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306043 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306044 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306045 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306046 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306047 out->standby = true;
6048 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306049 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006050 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6051 /* prevent division-by-zero */
6052 uint32_t stream_size = audio_stream_out_frame_size(stream);
6053 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006054
Dieter Luecking5d57def2018-09-07 14:23:37 +02006055 if ((stream_size == 0) || (srate == 0)) {
6056 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6057 ATRACE_END();
6058 return -EINVAL;
6059 }
6060 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6061 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006062 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306063 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006064 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006065 return ret;
6066 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006067 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006068 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006069 return bytes;
6070}
6071
6072static int out_get_render_position(const struct audio_stream_out *stream,
6073 uint32_t *dsp_frames)
6074{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006075 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006076
6077 if (dsp_frames == NULL)
6078 return -EINVAL;
6079
6080 *dsp_frames = 0;
6081 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006082 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306083
6084 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6085 * this operation and adev_close_output_stream(where out gets reset).
6086 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306087 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006088 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306089 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006090 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306091 return 0;
6092 }
6093
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006094 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306095 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306096 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006097 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306098 if (ret < 0)
6099 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006100 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306101 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006102 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306103 if (-ENETRESET == ret) {
6104 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306105 out->card_status = CARD_STATUS_OFFLINE;
6106 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306107 } else if(ret < 0) {
6108 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306109 ret = -EINVAL;
6110 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306111 /*
6112 * Handle corner case where compress session is closed during SSR
6113 * and timestamp is queried
6114 */
6115 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306116 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306117 } else if (out->prev_card_status_offline) {
6118 ALOGE("ERROR: previously sound card was offline,return error");
6119 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306120 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306121 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006122 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306123 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306124 pthread_mutex_unlock(&out->lock);
6125 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006126 } else if (audio_is_linear_pcm(out->format)) {
6127 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006128 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006129 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006130 } else
6131 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006132}
6133
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006134static int out_add_audio_effect(const struct audio_stream *stream __unused,
6135 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006136{
6137 return 0;
6138}
6139
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006140static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6141 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006142{
6143 return 0;
6144}
6145
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006146static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6147 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006148{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306149 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006150}
6151
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006152static int out_get_presentation_position(const struct audio_stream_out *stream,
6153 uint64_t *frames, struct timespec *timestamp)
6154{
6155 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306156 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006157 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006158
Ashish Jain5106d362016-05-11 19:23:33 +05306159 /* below piece of code is not guarded against any lock because audioFliner serializes
6160 * this operation and adev_close_output_stream( where out gets reset).
6161 */
6162 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306163 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006164 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306165 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6166 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6167 return 0;
6168 }
6169
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006170 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006171
Ashish Jain5106d362016-05-11 19:23:33 +05306172 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6173 ret = compress_get_tstamp(out->compr, &dsp_frames,
6174 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006175 // Adjustment accounts for A2dp encoder latency with offload usecases
6176 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006177 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006178 unsigned long offset =
6179 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6180 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6181 }
Ashish Jain5106d362016-05-11 19:23:33 +05306182 ALOGVV("%s rendered frames %ld sample_rate %d",
6183 __func__, dsp_frames, out->sample_rate);
6184 *frames = dsp_frames;
6185 if (ret < 0)
6186 ret = -errno;
6187 if (-ENETRESET == ret) {
6188 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306189 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306190 ret = -EINVAL;
6191 } else
6192 ret = 0;
6193 /* this is the best we can do */
6194 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006195 } else {
6196 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006197 unsigned int avail;
6198 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006199 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006200 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006201
Andy Hunga1f48fa2019-07-01 18:14:53 -07006202 if (out->kernel_buffer_size > avail) {
6203 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6204 } else {
6205 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6206 __func__, avail, out->kernel_buffer_size);
6207 avail = out->kernel_buffer_size;
6208 frames_temp = out->last_fifo_frames_remaining = 0;
6209 }
6210 out->last_fifo_valid = true;
6211 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6212
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006213 if (out->written >= frames_temp)
6214 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006215
Andy Hunga1f48fa2019-07-01 18:14:53 -07006216 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6217 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6218
Weiyin Jiangd4633762018-03-16 12:05:03 +08006219 // This adjustment accounts for buffering after app processor.
6220 // It is based on estimated DSP latency per use case, rather than exact.
Robert Lee58215542019-07-15 20:55:12 +08006221 pthread_mutex_lock(&adev->lock);
6222 frames_temp = platform_render_latency(out->dev, out->usecase) *
6223 out->sample_rate / 1000000LL;
6224 pthread_mutex_unlock(&adev->lock);
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006225 if (signed_frames >= frames_temp)
6226 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006227
Weiyin Jiangd4633762018-03-16 12:05:03 +08006228 // Adjustment accounts for A2dp encoder latency with non offload usecases
6229 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006230 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006231 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6232 if (signed_frames >= frames_temp)
6233 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006234 }
6235
6236 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006237 *frames = signed_frames;
6238 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006239 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006240 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6241 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006242 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306243 *frames = out->written;
6244 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306245 if (is_offload_usecase(out->usecase))
6246 ret = -EINVAL;
6247 else
6248 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006249 }
6250 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006251 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006252 return ret;
6253}
6254
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006255static int out_set_callback(struct audio_stream_out *stream,
6256 stream_callback_t callback, void *cookie)
6257{
6258 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006259 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006260
6261 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006262 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006263 out->client_callback = callback;
6264 out->client_cookie = cookie;
6265 if (out->adsp_hdlr_stream_handle) {
6266 ret = audio_extn_adsp_hdlr_stream_set_callback(
6267 out->adsp_hdlr_stream_handle,
6268 callback,
6269 cookie);
6270 if (ret)
6271 ALOGW("%s:adsp hdlr callback registration failed %d",
6272 __func__, ret);
6273 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006274 pthread_mutex_unlock(&out->lock);
6275 return 0;
6276}
6277
6278static int out_pause(struct audio_stream_out* stream)
6279{
6280 struct stream_out *out = (struct stream_out *)stream;
6281 int status = -ENOSYS;
6282 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006283 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006284 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306285 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006286 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006287 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306288 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306289 status = compress_pause(out->compr);
6290
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006291 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006292
Mingming Yin21854652016-04-13 11:54:02 -07006293 if (audio_extn_passthru_is_active()) {
6294 ALOGV("offload use case, pause passthru");
6295 audio_extn_passthru_on_pause(out);
6296 }
6297
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306298 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006299 audio_extn_dts_notify_playback_state(out->usecase, 0,
6300 out->sample_rate, popcount(out->channel_mask),
6301 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006302 }
6303 pthread_mutex_unlock(&out->lock);
6304 }
6305 return status;
6306}
6307
6308static int out_resume(struct audio_stream_out* stream)
6309{
6310 struct stream_out *out = (struct stream_out *)stream;
6311 int status = -ENOSYS;
6312 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006313 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006314 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306315 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006316 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006317 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306318 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306319 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006320 }
6321 if (!status) {
6322 out->offload_state = OFFLOAD_STATE_PLAYING;
6323 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306324 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006325 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6326 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006327 }
6328 pthread_mutex_unlock(&out->lock);
6329 }
6330 return status;
6331}
6332
6333static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6334{
6335 struct stream_out *out = (struct stream_out *)stream;
6336 int status = -ENOSYS;
6337 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006338 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006339 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006340 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6341 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6342 else
6343 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6344 pthread_mutex_unlock(&out->lock);
6345 }
6346 return status;
6347}
6348
6349static int out_flush(struct audio_stream_out* stream)
6350{
6351 struct stream_out *out = (struct stream_out *)stream;
6352 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006353 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006354 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006355 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006356 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6357 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006358 } else {
6359 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6360 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006361 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006362 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006363 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006364 return 0;
6365 }
6366 return -ENOSYS;
6367}
6368
Haynes Mathew George16081042017-05-31 17:16:49 -07006369static int out_stop(const struct audio_stream_out* stream)
6370{
6371 struct stream_out *out = (struct stream_out *)stream;
6372 struct audio_device *adev = out->dev;
6373 int ret = -ENOSYS;
6374
6375 ALOGV("%s", __func__);
6376 pthread_mutex_lock(&adev->lock);
6377 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6378 out->playback_started && out->pcm != NULL) {
6379 pcm_stop(out->pcm);
6380 ret = stop_output_stream(out);
6381 out->playback_started = false;
6382 }
6383 pthread_mutex_unlock(&adev->lock);
6384 return ret;
6385}
6386
6387static int out_start(const struct audio_stream_out* stream)
6388{
6389 struct stream_out *out = (struct stream_out *)stream;
6390 struct audio_device *adev = out->dev;
6391 int ret = -ENOSYS;
6392
6393 ALOGV("%s", __func__);
6394 pthread_mutex_lock(&adev->lock);
6395 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6396 !out->playback_started && out->pcm != NULL) {
6397 ret = start_output_stream(out);
6398 if (ret == 0) {
6399 out->playback_started = true;
6400 }
6401 }
6402 pthread_mutex_unlock(&adev->lock);
6403 return ret;
6404}
6405
6406/*
6407 * Modify config->period_count based on min_size_frames
6408 */
6409static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6410{
6411 int periodCountRequested = (min_size_frames + config->period_size - 1)
6412 / config->period_size;
6413 int periodCount = MMAP_PERIOD_COUNT_MIN;
6414
6415 ALOGV("%s original config.period_size = %d config.period_count = %d",
6416 __func__, config->period_size, config->period_count);
6417
6418 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6419 periodCount *= 2;
6420 }
6421 config->period_count = periodCount;
6422
6423 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6424}
6425
Phil Burkfe17efd2019-03-25 10:23:35 -07006426// Read offset for the positional timestamp from a persistent vendor property.
6427// This is to workaround apparent inaccuracies in the timing information that
6428// is used by the AAudio timing model. The inaccuracies can cause glitches.
6429static int64_t get_mmap_out_time_offset() {
6430 const int32_t kDefaultOffsetMicros = 0;
6431 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006432 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006433 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6434 return mmap_time_offset_micros * (int64_t)1000;
6435}
6436
Haynes Mathew George16081042017-05-31 17:16:49 -07006437static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6438 int32_t min_size_frames,
6439 struct audio_mmap_buffer_info *info)
6440{
6441 struct stream_out *out = (struct stream_out *)stream;
6442 struct audio_device *adev = out->dev;
6443 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006444 unsigned int offset1 = 0;
6445 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006446 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006447 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006448 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006449
Arun Mirpuri5d170872019-03-26 13:21:31 -07006450 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306451 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006452 pthread_mutex_lock(&adev->lock);
6453
Sharad Sanglec6f32552018-05-04 16:15:38 +05306454 if (CARD_STATUS_OFFLINE == out->card_status ||
6455 CARD_STATUS_OFFLINE == adev->card_status) {
6456 ALOGW("out->card_status or adev->card_status offline, try again");
6457 ret = -EIO;
6458 goto exit;
6459 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306460 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006461 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6462 ret = -EINVAL;
6463 goto exit;
6464 }
6465 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6466 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6467 ret = -ENOSYS;
6468 goto exit;
6469 }
6470 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6471 if (out->pcm_device_id < 0) {
6472 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6473 __func__, out->pcm_device_id, out->usecase);
6474 ret = -EINVAL;
6475 goto exit;
6476 }
6477
6478 adjust_mmap_period_count(&out->config, min_size_frames);
6479
Arun Mirpuri5d170872019-03-26 13:21:31 -07006480 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006481 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6482 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6483 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306484 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306485 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6486 out->card_status = CARD_STATUS_OFFLINE;
6487 adev->card_status = CARD_STATUS_OFFLINE;
6488 ret = -EIO;
6489 goto exit;
6490 }
6491
Haynes Mathew George16081042017-05-31 17:16:49 -07006492 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6493 step = "open";
6494 ret = -ENODEV;
6495 goto exit;
6496 }
6497 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6498 if (ret < 0) {
6499 step = "begin";
6500 goto exit;
6501 }
juyuchen626833d2019-06-04 16:48:02 +08006502
6503 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006504 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006505 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006506 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006507 ret = platform_get_mmap_data_fd(adev->platform,
6508 out->pcm_device_id, 0 /*playback*/,
6509 &info->shared_memory_fd,
6510 &mmap_size);
6511 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006512 // Fall back to non exclusive mode
6513 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6514 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006515 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6516 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6517
Arun Mirpuri5d170872019-03-26 13:21:31 -07006518 if (mmap_size < buffer_size) {
6519 step = "mmap";
6520 goto exit;
6521 }
juyuchen626833d2019-06-04 16:48:02 +08006522 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006523 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006524 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006525 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006526
6527 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6528 if (ret < 0) {
6529 step = "commit";
6530 goto exit;
6531 }
6532
Phil Burkfe17efd2019-03-25 10:23:35 -07006533 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6534
Haynes Mathew George16081042017-05-31 17:16:49 -07006535 out->standby = false;
6536 ret = 0;
6537
Arun Mirpuri5d170872019-03-26 13:21:31 -07006538 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006539 __func__, info->shared_memory_address, info->buffer_size_frames);
6540
6541exit:
6542 if (ret != 0) {
6543 if (out->pcm == NULL) {
6544 ALOGE("%s: %s - %d", __func__, step, ret);
6545 } else {
6546 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6547 pcm_close(out->pcm);
6548 out->pcm = NULL;
6549 }
6550 }
6551 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306552 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006553 return ret;
6554}
6555
6556static int out_get_mmap_position(const struct audio_stream_out *stream,
6557 struct audio_mmap_position *position)
6558{
6559 struct stream_out *out = (struct stream_out *)stream;
6560 ALOGVV("%s", __func__);
6561 if (position == NULL) {
6562 return -EINVAL;
6563 }
6564 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006565 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006566 return -ENOSYS;
6567 }
6568 if (out->pcm == NULL) {
6569 return -ENOSYS;
6570 }
6571
6572 struct timespec ts = { 0, 0 };
6573 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6574 if (ret < 0) {
6575 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6576 return ret;
6577 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006578 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6579 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006580 return 0;
6581}
6582
6583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006584/** audio_stream_in implementation **/
6585static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6586{
6587 struct stream_in *in = (struct stream_in *)stream;
6588
6589 return in->config.rate;
6590}
6591
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006592static int in_set_sample_rate(struct audio_stream *stream __unused,
6593 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006594{
6595 return -ENOSYS;
6596}
6597
6598static size_t in_get_buffer_size(const struct audio_stream *stream)
6599{
6600 struct stream_in *in = (struct stream_in *)stream;
6601
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006602 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6603 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006604 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6605 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306606 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306607 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006608
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006609 return in->config.period_size * in->af_period_multiplier *
6610 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006611}
6612
6613static uint32_t in_get_channels(const struct audio_stream *stream)
6614{
6615 struct stream_in *in = (struct stream_in *)stream;
6616
6617 return in->channel_mask;
6618}
6619
6620static audio_format_t in_get_format(const struct audio_stream *stream)
6621{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006622 struct stream_in *in = (struct stream_in *)stream;
6623
6624 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006625}
6626
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006627static int in_set_format(struct audio_stream *stream __unused,
6628 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006629{
6630 return -ENOSYS;
6631}
6632
6633static int in_standby(struct audio_stream *stream)
6634{
6635 struct stream_in *in = (struct stream_in *)stream;
6636 struct audio_device *adev = in->dev;
6637 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306638 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6639 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006640 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306641
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006642 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006643 if (!in->standby && in->is_st_session) {
6644 ALOGD("%s: sound trigger pcm stop lab", __func__);
6645 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006646 if (adev->num_va_sessions > 0)
6647 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006648 in->standby = 1;
6649 }
6650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006651 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006652 if (adev->adm_deregister_stream)
6653 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6654
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006655 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006656 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006657 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006658 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006659 voice_extn_compress_voip_close_input_stream(stream);
6660 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006661 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6662 do_stop = in->capture_started;
6663 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006664 if (in->mmap_shared_memory_fd >= 0) {
6665 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6666 __func__, in->mmap_shared_memory_fd);
6667 close(in->mmap_shared_memory_fd);
6668 in->mmap_shared_memory_fd = -1;
6669 }
Zhou Songa8895042016-07-05 17:54:22 +08006670 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306671 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306672 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006673 }
6674
Arun Mirpuri5d170872019-03-26 13:21:31 -07006675 if (in->pcm) {
6676 ATRACE_BEGIN("pcm_in_close");
6677 pcm_close(in->pcm);
6678 ATRACE_END();
6679 in->pcm = NULL;
6680 }
6681
Carter Hsu2e429db2019-05-14 18:50:52 +08006682 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006683 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006684
George Gao3018ede2019-10-23 13:23:00 -07006685 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6686 if (adev->num_va_sessions > 0)
6687 adev->num_va_sessions--;
6688 }
Quinn Malef6050362019-01-30 15:55:40 -08006689
Eric Laurent150dbfe2013-02-27 14:31:02 -08006690 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006691 }
6692 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006693 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006694 return status;
6695}
6696
Aalique Grahame22e49102018-12-18 14:23:57 -08006697static int in_dump(const struct audio_stream *stream,
6698 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006699{
Aalique Grahame22e49102018-12-18 14:23:57 -08006700 struct stream_in *in = (struct stream_in *)stream;
6701
6702 // We try to get the lock for consistency,
6703 // but it isn't necessary for these variables.
6704 // If we're not in standby, we may be blocked on a read.
6705 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6706 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6707 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6708 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6709
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006710 char buffer[256]; // for statistics formatting
6711 if (in->start_latency_ms.n > 0) {
6712 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6713 dprintf(fd, " Start latency ms: %s\n", buffer);
6714 }
6715
Aalique Grahame22e49102018-12-18 14:23:57 -08006716 if (locked) {
6717 pthread_mutex_unlock(&in->lock);
6718 }
6719
6720 // dump error info
6721 (void)error_log_dump(
6722 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006724 return 0;
6725}
6726
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306727static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6728{
6729 if (!stream || !parms)
6730 return;
6731
6732 struct stream_in *in = (struct stream_in *)stream;
6733 struct audio_device *adev = in->dev;
6734
6735 card_status_t status;
6736 int card;
6737 if (parse_snd_card_status(parms, &card, &status) < 0)
6738 return;
6739
6740 pthread_mutex_lock(&adev->lock);
6741 bool valid_cb = (card == adev->snd_card);
6742 pthread_mutex_unlock(&adev->lock);
6743
6744 if (!valid_cb)
6745 return;
6746
6747 lock_input_stream(in);
6748 if (in->card_status != status)
6749 in->card_status = status;
6750 pthread_mutex_unlock(&in->lock);
6751
6752 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6753 use_case_table[in->usecase],
6754 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6755
6756 // a better solution would be to report error back to AF and let
6757 // it put the stream to standby
6758 if (status == CARD_STATUS_OFFLINE)
6759 in_standby(&in->stream.common);
6760
6761 return;
6762}
6763
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006764int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006765 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006766 audio_source_t source)
6767{
6768 struct audio_device *adev = in->dev;
6769 int ret = 0;
6770
6771 lock_input_stream(in);
6772 pthread_mutex_lock(&adev->lock);
6773
6774 /* no audio source uses val == 0 */
6775 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6776 in->source = source;
6777 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6778 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6779 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6780 (in->config.rate == 8000 || in->config.rate == 16000 ||
6781 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6782 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6783 ret = voice_extn_compress_voip_open_input_stream(in);
6784 if (ret != 0) {
6785 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6786 __func__, ret);
6787 }
6788 }
6789 }
6790
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006791 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6792 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006793 // Workaround: If routing to an non existing usb device, fail gracefully
6794 // The routing request will otherwise block during 10 second
6795 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006796 struct str_parms *usb_addr =
6797 str_parms_create_str(get_usb_device_address(devices));
6798 if (is_usb_in_device_type(devices) && usb_addr &&
6799 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006800 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6801 ret = -ENOSYS;
6802 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006803 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006804 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006805 if (!in->standby && !in->is_st_session) {
6806 ALOGV("update input routing change");
6807 // inform adm before actual routing to prevent glitches.
6808 if (adev->adm_on_routing_change) {
6809 adev->adm_on_routing_change(adev->adm_data,
6810 in->capture_handle);
6811 ret = select_devices(adev, in->usecase);
6812 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6813 adev->adm_routing_changed = true;
6814 }
6815 }
6816 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006817 if (usb_addr)
6818 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006819 }
6820 pthread_mutex_unlock(&adev->lock);
6821 pthread_mutex_unlock(&in->lock);
6822
6823 ALOGD("%s: exit: status(%d)", __func__, ret);
6824 return ret;
6825}
6826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006827static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6828{
6829 struct stream_in *in = (struct stream_in *)stream;
6830 struct audio_device *adev = in->dev;
6831 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006832 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306833 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006834
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306835 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006836 parms = str_parms_create_str(kvpairs);
6837
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306838 if (!parms)
6839 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006840 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006841 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006842
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306843 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6844 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306845 strlcpy(in->profile, value, sizeof(in->profile));
6846 ALOGV("updating stream profile with value '%s'", in->profile);
6847 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6848 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006849 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306850 in->sample_rate, in->bit_width,
6851 in->profile, &in->app_type_cfg);
6852 }
6853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006854 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006855 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006856
6857 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306858error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306859 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006860}
6861
6862static char* in_get_parameters(const struct audio_stream *stream,
6863 const char *keys)
6864{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006865 struct stream_in *in = (struct stream_in *)stream;
6866 struct str_parms *query = str_parms_create_str(keys);
6867 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006868 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006869
6870 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006871 if (reply) {
6872 str_parms_destroy(reply);
6873 }
6874 if (query) {
6875 str_parms_destroy(query);
6876 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006877 ALOGE("in_get_parameters: failed to create query or reply");
6878 return NULL;
6879 }
6880
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006881 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006882
6883 voice_extn_in_get_parameters(in, query, reply);
6884
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006885 stream_get_parameter_channels(query, reply,
6886 &in->supported_channel_masks[0]);
6887 stream_get_parameter_formats(query, reply,
6888 &in->supported_formats[0]);
6889 stream_get_parameter_rates(query, reply,
6890 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006891 str = str_parms_to_str(reply);
6892 str_parms_destroy(query);
6893 str_parms_destroy(reply);
6894
6895 ALOGV("%s: exit: returns - %s", __func__, str);
6896 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006897}
6898
Aalique Grahame22e49102018-12-18 14:23:57 -08006899static int in_set_gain(struct audio_stream_in *stream,
6900 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006901{
Aalique Grahame22e49102018-12-18 14:23:57 -08006902 struct stream_in *in = (struct stream_in *)stream;
6903 char mixer_ctl_name[128];
6904 struct mixer_ctl *ctl;
6905 int ctl_value;
6906
6907 ALOGV("%s: gain %f", __func__, gain);
6908
6909 if (stream == NULL)
6910 return -EINVAL;
6911
6912 /* in_set_gain() only used to silence MMAP capture for now */
6913 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6914 return -ENOSYS;
6915
6916 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6917
6918 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6919 if (!ctl) {
6920 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6921 __func__, mixer_ctl_name);
6922 return -ENOSYS;
6923 }
6924
6925 if (gain < RECORD_GAIN_MIN)
6926 gain = RECORD_GAIN_MIN;
6927 else if (gain > RECORD_GAIN_MAX)
6928 gain = RECORD_GAIN_MAX;
6929 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6930
6931 mixer_ctl_set_value(ctl, 0, ctl_value);
6932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006933 return 0;
6934}
6935
6936static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6937 size_t bytes)
6938{
6939 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306940
6941 if (in == NULL) {
6942 ALOGE("%s: stream_in ptr is NULL", __func__);
6943 return -EINVAL;
6944 }
6945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006946 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306947 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306948 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006949
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006950 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306951
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006952 if (in->is_st_session) {
6953 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6954 /* Read from sound trigger HAL */
6955 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006956 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006957 if (adev->num_va_sessions < UINT_MAX)
6958 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006959 in->standby = 0;
6960 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006961 pthread_mutex_unlock(&in->lock);
6962 return bytes;
6963 }
6964
Haynes Mathew George16081042017-05-31 17:16:49 -07006965 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6966 ret = -ENOSYS;
6967 goto exit;
6968 }
6969
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006970 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6971 !in->standby && adev->adm_routing_changed) {
6972 ret = -ENOSYS;
6973 goto exit;
6974 }
6975
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006976 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006977 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6978
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006979 pthread_mutex_lock(&adev->lock);
6980 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6981 ret = voice_extn_compress_voip_start_input_stream(in);
6982 else
6983 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006984 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6985 if (adev->num_va_sessions < UINT_MAX)
6986 adev->num_va_sessions++;
6987 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006988 pthread_mutex_unlock(&adev->lock);
6989 if (ret != 0) {
6990 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006991 }
6992 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006993
6994 // log startup time in ms.
6995 simple_stats_log(
6996 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006997 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006998
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306999 /* Avoid read if capture_stopped is set */
7000 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7001 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7002 ret = -EINVAL;
7003 goto exit;
7004 }
7005
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007006 // what's the duration requested by the client?
7007 long ns = 0;
7008
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307009 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007010 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7011 in->config.rate;
7012
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007013 ret = request_in_focus(in, ns);
7014 if (ret != 0)
7015 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007016 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007017
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307018 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307019 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7020 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307021 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007022 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307023 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007024 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007025 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007026 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007027 } else if (audio_extn_ffv_get_stream() == in) {
7028 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307029 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007030 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307031 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7032 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7033 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7034 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307035 ret = -EINVAL;
7036 goto exit;
7037 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307038 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307039 ret = -errno;
7040 }
7041 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307042 /* bytes read is always set to bytes for non compress usecases */
7043 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007044 }
7045
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007046 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007048 /*
Quinn Malef6050362019-01-30 15:55:40 -08007049 * Instead of writing zeroes here, we could trust the hardware to always
7050 * provide zeroes when muted. This is also muted with voice recognition
7051 * usecases so that other clients do not have access to voice recognition
7052 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007053 */
Quinn Malef6050362019-01-30 15:55:40 -08007054 if ((ret == 0 && voice_get_mic_mute(adev) &&
7055 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007056 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7057 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007058 (adev->num_va_sessions &&
7059 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7060 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7061 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007062 memset(buffer, 0, bytes);
7063
7064exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307065 frame_size = audio_stream_in_frame_size(stream);
7066 if (frame_size > 0)
7067 in->frames_read += bytes_read/frame_size;
7068
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007069 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307070 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007071 pthread_mutex_unlock(&in->lock);
7072
7073 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307074 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307075 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307076 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307077 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307078 in->standby = true;
7079 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307080 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307081 bytes_read = bytes;
7082 memset(buffer, 0, bytes);
7083 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007084 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007085 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7086 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007087 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307088 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307089 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007090 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307091 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007092}
7093
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007094static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007095{
7096 return 0;
7097}
7098
Aalique Grahame22e49102018-12-18 14:23:57 -08007099static int in_get_capture_position(const struct audio_stream_in *stream,
7100 int64_t *frames, int64_t *time)
7101{
7102 if (stream == NULL || frames == NULL || time == NULL) {
7103 return -EINVAL;
7104 }
7105 struct stream_in *in = (struct stream_in *)stream;
7106 int ret = -ENOSYS;
7107
7108 lock_input_stream(in);
7109 // note: ST sessions do not close the alsa pcm driver synchronously
7110 // on standby. Therefore, we may return an error even though the
7111 // pcm stream is still opened.
7112 if (in->standby) {
7113 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7114 "%s stream in standby but pcm not NULL for non ST session", __func__);
7115 goto exit;
7116 }
7117 if (in->pcm) {
7118 struct timespec timestamp;
7119 unsigned int avail;
7120 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7121 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007122 pthread_mutex_lock(&adev->lock);
7123 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
7124 - platform_capture_latency(in->dev, in->usecase) * 1000LL;
7125 pthread_mutex_unlock(&adev->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08007126 ret = 0;
7127 }
7128 }
7129exit:
7130 pthread_mutex_unlock(&in->lock);
7131 return ret;
7132}
7133
Carter Hsu2e429db2019-05-14 18:50:52 +08007134static int in_update_effect_list(bool add, effect_handle_t effect,
7135 struct listnode *head)
7136{
7137 struct listnode *node;
7138 struct in_effect_list *elist = NULL;
7139 struct in_effect_list *target = NULL;
7140 int ret = 0;
7141
7142 if (!head)
7143 return ret;
7144
7145 list_for_each(node, head) {
7146 elist = node_to_item(node, struct in_effect_list, list);
7147 if (elist->handle == effect) {
7148 target = elist;
7149 break;
7150 }
7151 }
7152
7153 if (add) {
7154 if (target) {
7155 ALOGD("effect %p already exist", effect);
7156 return ret;
7157 }
7158
7159 target = (struct in_effect_list *)
7160 calloc(1, sizeof(struct in_effect_list));
7161
7162 if (!target) {
7163 ALOGE("%s:fail to allocate memory", __func__);
7164 return -ENOMEM;
7165 }
7166
7167 target->handle = effect;
7168 list_add_tail(head, &target->list);
7169 } else {
7170 if (target) {
7171 list_remove(&target->list);
7172 free(target);
7173 }
7174 }
7175
7176 return ret;
7177}
7178
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007179static int add_remove_audio_effect(const struct audio_stream *stream,
7180 effect_handle_t effect,
7181 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007182{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007183 struct stream_in *in = (struct stream_in *)stream;
7184 int status = 0;
7185 effect_descriptor_t desc;
7186
7187 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007188 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7189
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007190 if (status != 0)
7191 return status;
7192
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007193 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007194 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007195 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007196 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7197 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007198 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007199
7200 in_update_effect_list(enable, effect, &in->aec_list);
7201 enable = !list_empty(&in->aec_list);
7202 if (enable == in->enable_aec)
7203 goto exit;
7204
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007205 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007206 ALOGD("AEC enable %d", enable);
7207
Aalique Grahame22e49102018-12-18 14:23:57 -08007208 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7209 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7210 in->dev->enable_voicerx = enable;
7211 struct audio_usecase *usecase;
7212 struct listnode *node;
7213 list_for_each(node, &in->dev->usecase_list) {
7214 usecase = node_to_item(node, struct audio_usecase, list);
7215 if (usecase->type == PCM_PLAYBACK)
7216 select_devices(in->dev, usecase->id);
7217 }
7218 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007219 if (!in->standby) {
7220 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7221 select_devices(in->dev, in->usecase);
7222 }
7223
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007224 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007225 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7226
7227 in_update_effect_list(enable, effect, &in->ns_list);
7228 enable = !list_empty(&in->ns_list);
7229 if (enable == in->enable_ns)
7230 goto exit;
7231
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007232 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007233 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007234 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007235 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7236 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007237 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7238 select_devices(in->dev, in->usecase);
7239 } else
7240 select_devices(in->dev, in->usecase);
7241 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007242 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007243exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007244 pthread_mutex_unlock(&in->dev->lock);
7245 pthread_mutex_unlock(&in->lock);
7246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007247 return 0;
7248}
7249
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007250static int in_add_audio_effect(const struct audio_stream *stream,
7251 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007252{
Eric Laurent994a6932013-07-17 11:51:42 -07007253 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007254 return add_remove_audio_effect(stream, effect, true);
7255}
7256
7257static int in_remove_audio_effect(const struct audio_stream *stream,
7258 effect_handle_t effect)
7259{
Eric Laurent994a6932013-07-17 11:51:42 -07007260 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007261 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007262}
7263
Derek Chenf939fb72018-11-13 13:34:41 -08007264streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7265 audio_io_handle_t input)
7266{
7267 struct listnode *node;
7268
7269 list_for_each(node, &dev->active_inputs_list) {
7270 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7271 streams_input_ctxt_t,
7272 list);
7273 if (in_ctxt->input->capture_handle == input) {
7274 return in_ctxt;
7275 }
7276 }
7277 return NULL;
7278}
7279
7280streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7281 audio_io_handle_t output)
7282{
7283 struct listnode *node;
7284
7285 list_for_each(node, &dev->active_outputs_list) {
7286 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7287 streams_output_ctxt_t,
7288 list);
7289 if (out_ctxt->output->handle == output) {
7290 return out_ctxt;
7291 }
7292 }
7293 return NULL;
7294}
7295
Haynes Mathew George16081042017-05-31 17:16:49 -07007296static int in_stop(const struct audio_stream_in* stream)
7297{
7298 struct stream_in *in = (struct stream_in *)stream;
7299 struct audio_device *adev = in->dev;
7300
7301 int ret = -ENOSYS;
7302 ALOGV("%s", __func__);
7303 pthread_mutex_lock(&adev->lock);
7304 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7305 in->capture_started && in->pcm != NULL) {
7306 pcm_stop(in->pcm);
7307 ret = stop_input_stream(in);
7308 in->capture_started = false;
7309 }
7310 pthread_mutex_unlock(&adev->lock);
7311 return ret;
7312}
7313
7314static int in_start(const struct audio_stream_in* stream)
7315{
7316 struct stream_in *in = (struct stream_in *)stream;
7317 struct audio_device *adev = in->dev;
7318 int ret = -ENOSYS;
7319
7320 ALOGV("%s in %p", __func__, in);
7321 pthread_mutex_lock(&adev->lock);
7322 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7323 !in->capture_started && in->pcm != NULL) {
7324 if (!in->capture_started) {
7325 ret = start_input_stream(in);
7326 if (ret == 0) {
7327 in->capture_started = true;
7328 }
7329 }
7330 }
7331 pthread_mutex_unlock(&adev->lock);
7332 return ret;
7333}
7334
Phil Burke0a86d12019-02-16 22:28:11 -08007335// Read offset for the positional timestamp from a persistent vendor property.
7336// This is to workaround apparent inaccuracies in the timing information that
7337// is used by the AAudio timing model. The inaccuracies can cause glitches.
7338static int64_t in_get_mmap_time_offset() {
7339 const int32_t kDefaultOffsetMicros = 0;
7340 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007341 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007342 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7343 return mmap_time_offset_micros * (int64_t)1000;
7344}
7345
Haynes Mathew George16081042017-05-31 17:16:49 -07007346static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7347 int32_t min_size_frames,
7348 struct audio_mmap_buffer_info *info)
7349{
7350 struct stream_in *in = (struct stream_in *)stream;
7351 struct audio_device *adev = in->dev;
7352 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007353 unsigned int offset1 = 0;
7354 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007355 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007356 uint32_t mmap_size = 0;
7357 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007358
7359 pthread_mutex_lock(&adev->lock);
7360 ALOGV("%s in %p", __func__, in);
7361
Sharad Sanglec6f32552018-05-04 16:15:38 +05307362 if (CARD_STATUS_OFFLINE == in->card_status||
7363 CARD_STATUS_OFFLINE == adev->card_status) {
7364 ALOGW("in->card_status or adev->card_status offline, try again");
7365 ret = -EIO;
7366 goto exit;
7367 }
7368
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307369 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007370 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7371 ret = -EINVAL;
7372 goto exit;
7373 }
7374 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7375 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7376 ALOGV("%s in %p", __func__, in);
7377 ret = -ENOSYS;
7378 goto exit;
7379 }
7380 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7381 if (in->pcm_device_id < 0) {
7382 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7383 __func__, in->pcm_device_id, in->usecase);
7384 ret = -EINVAL;
7385 goto exit;
7386 }
7387
7388 adjust_mmap_period_count(&in->config, min_size_frames);
7389
7390 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7391 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7392 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7393 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307394 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307395 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7396 in->card_status = CARD_STATUS_OFFLINE;
7397 adev->card_status = CARD_STATUS_OFFLINE;
7398 ret = -EIO;
7399 goto exit;
7400 }
7401
Haynes Mathew George16081042017-05-31 17:16:49 -07007402 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7403 step = "open";
7404 ret = -ENODEV;
7405 goto exit;
7406 }
7407
7408 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7409 if (ret < 0) {
7410 step = "begin";
7411 goto exit;
7412 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007413
juyuchen626833d2019-06-04 16:48:02 +08007414 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007415 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7416 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7417 info->burst_size_frames = in->config.period_size;
7418 ret = platform_get_mmap_data_fd(adev->platform,
7419 in->pcm_device_id, 1 /*capture*/,
7420 &info->shared_memory_fd,
7421 &mmap_size);
7422 if (ret < 0) {
7423 // Fall back to non exclusive mode
7424 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7425 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007426 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7427 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7428
Arun Mirpuri5d170872019-03-26 13:21:31 -07007429 if (mmap_size < buffer_size) {
7430 step = "mmap";
7431 goto exit;
7432 }
juyuchen626833d2019-06-04 16:48:02 +08007433 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007434 }
7435
7436 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007437
7438 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7439 if (ret < 0) {
7440 step = "commit";
7441 goto exit;
7442 }
7443
Phil Burke0a86d12019-02-16 22:28:11 -08007444 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7445
Haynes Mathew George16081042017-05-31 17:16:49 -07007446 in->standby = false;
7447 ret = 0;
7448
7449 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7450 __func__, info->shared_memory_address, info->buffer_size_frames);
7451
7452exit:
7453 if (ret != 0) {
7454 if (in->pcm == NULL) {
7455 ALOGE("%s: %s - %d", __func__, step, ret);
7456 } else {
7457 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7458 pcm_close(in->pcm);
7459 in->pcm = NULL;
7460 }
7461 }
7462 pthread_mutex_unlock(&adev->lock);
7463 return ret;
7464}
7465
7466static int in_get_mmap_position(const struct audio_stream_in *stream,
7467 struct audio_mmap_position *position)
7468{
7469 struct stream_in *in = (struct stream_in *)stream;
7470 ALOGVV("%s", __func__);
7471 if (position == NULL) {
7472 return -EINVAL;
7473 }
7474 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7475 return -ENOSYS;
7476 }
7477 if (in->pcm == NULL) {
7478 return -ENOSYS;
7479 }
7480 struct timespec ts = { 0, 0 };
7481 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7482 if (ret < 0) {
7483 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7484 return ret;
7485 }
Phil Burke0a86d12019-02-16 22:28:11 -08007486 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7487 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007488 return 0;
7489}
7490
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307491static int in_get_active_microphones(const struct audio_stream_in *stream,
7492 struct audio_microphone_characteristic_t *mic_array,
7493 size_t *mic_count) {
7494 struct stream_in *in = (struct stream_in *)stream;
7495 struct audio_device *adev = in->dev;
7496 ALOGVV("%s", __func__);
7497
7498 lock_input_stream(in);
7499 pthread_mutex_lock(&adev->lock);
7500 int ret = platform_get_active_microphones(adev->platform,
7501 audio_channel_count_from_in_mask(in->channel_mask),
7502 in->usecase, mic_array, mic_count);
7503 pthread_mutex_unlock(&adev->lock);
7504 pthread_mutex_unlock(&in->lock);
7505
7506 return ret;
7507}
7508
7509static int adev_get_microphones(const struct audio_hw_device *dev,
7510 struct audio_microphone_characteristic_t *mic_array,
7511 size_t *mic_count) {
7512 struct audio_device *adev = (struct audio_device *)dev;
7513 ALOGVV("%s", __func__);
7514
7515 pthread_mutex_lock(&adev->lock);
7516 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7517 pthread_mutex_unlock(&adev->lock);
7518
7519 return ret;
7520}
juyuchendb308c22019-01-21 11:57:17 -07007521
7522static void in_update_sink_metadata(struct audio_stream_in *stream,
7523 const struct sink_metadata *sink_metadata) {
7524
7525 if (stream == NULL
7526 || sink_metadata == NULL
7527 || sink_metadata->tracks == NULL) {
7528 return;
7529 }
7530
7531 int error = 0;
7532 struct stream_in *in = (struct stream_in *)stream;
7533 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007534 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007535 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007536
7537 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007538
7539 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007540 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007541
7542 lock_input_stream(in);
7543 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007544 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007545
Zhou Song62ea0282020-03-22 19:53:01 +08007546 is_ha_usecase = adev->ha_proxy_enable ?
7547 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7548 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7549 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007550 && adev->voice_tx_output != NULL) {
7551 /* Use the rx device from afe-proxy record to route voice call because
7552 there is no routing if tx device is on primary hal and rx device
7553 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007554 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007555
7556 if (!voice_is_call_state_active(adev)) {
7557 if (adev->mode == AUDIO_MODE_IN_CALL) {
7558 adev->current_call_output = adev->voice_tx_output;
7559 error = voice_start_call(adev);
7560 if (error != 0)
7561 ALOGE("%s: start voice call failed %d", __func__, error);
7562 }
7563 } else {
7564 adev->current_call_output = adev->voice_tx_output;
7565 voice_update_devices_for_all_voice_usecases(adev);
7566 }
7567 }
7568
7569 pthread_mutex_unlock(&adev->lock);
7570 pthread_mutex_unlock(&in->lock);
7571}
7572
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307573int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007574 audio_io_handle_t handle,
7575 audio_devices_t devices,
7576 audio_output_flags_t flags,
7577 struct audio_config *config,
7578 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007579 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007580{
7581 struct audio_device *adev = (struct audio_device *)dev;
7582 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307583 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007584 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007585 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307586 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007587 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7588 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7589 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7590 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007591 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007592 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7593 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007594 bool force_haptic_path =
7595 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007596 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007597
kunleizdff872d2018-08-20 14:40:33 +08007598 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007599 is_usb_dev = false;
7600 devices = AUDIO_DEVICE_OUT_SPEAKER;
7601 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7602 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007603 if (config->format == AUDIO_FORMAT_DEFAULT)
7604 config->format = AUDIO_FORMAT_PCM_16_BIT;
7605 if (config->sample_rate == 0)
7606 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7607 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7608 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007609 }
7610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007611 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307612
Rahul Sharma99770982019-03-06 17:05:26 +05307613 pthread_mutex_lock(&adev->lock);
7614 if (out_get_stream(adev, handle) != NULL) {
7615 ALOGW("%s, output stream already opened", __func__);
7616 ret = -EEXIST;
7617 }
7618 pthread_mutex_unlock(&adev->lock);
7619 if (ret)
7620 return ret;
7621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007622 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7623
Mingming Yin3a941d42016-02-17 18:08:05 -08007624 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007625 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7626 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307627
7628
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007629 if (!out) {
7630 return -ENOMEM;
7631 }
7632
Haynes Mathew George204045b2015-02-25 20:32:03 -08007633 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007634 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307635 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007636 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007637 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007639 if (devices == AUDIO_DEVICE_NONE)
7640 devices = AUDIO_DEVICE_OUT_SPEAKER;
7641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007642 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007643 list_init(&out->device_list);
7644 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007645 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007646 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007647 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307648 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307649 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7650 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7651 else
7652 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007653 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007654 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007655 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307656 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307657 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307658 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007659 out->hal_output_suspend_supported = 0;
7660 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307661 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307662 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307663 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007664 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007665
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307666 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307667 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007668 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7669
Aalique Grahame22e49102018-12-18 14:23:57 -08007670 if (direct_dev &&
7671 (audio_is_linear_pcm(out->format) ||
7672 config->format == AUDIO_FORMAT_DEFAULT) &&
7673 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7674 audio_format_t req_format = config->format;
7675 audio_channel_mask_t req_channel_mask = config->channel_mask;
7676 uint32_t req_sample_rate = config->sample_rate;
7677
7678 pthread_mutex_lock(&adev->lock);
7679 if (is_hdmi) {
7680 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7681 ret = read_hdmi_sink_caps(out);
7682 if (config->sample_rate == 0)
7683 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7684 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7685 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7686 if (config->format == AUDIO_FORMAT_DEFAULT)
7687 config->format = AUDIO_FORMAT_PCM_16_BIT;
7688 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007689 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7690 &config->format,
7691 &out->supported_formats[0],
7692 MAX_SUPPORTED_FORMATS,
7693 &config->channel_mask,
7694 &out->supported_channel_masks[0],
7695 MAX_SUPPORTED_CHANNEL_MASKS,
7696 &config->sample_rate,
7697 &out->supported_sample_rates[0],
7698 MAX_SUPPORTED_SAMPLE_RATES);
7699 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007700 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007701
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007702 pthread_mutex_unlock(&adev->lock);
7703 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007704 if (ret == -ENOSYS) {
7705 /* ignore and go with default */
7706 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007707 }
7708 // For MMAP NO IRQ, allow conversions in ADSP
7709 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7710 goto error_open;
7711 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007712 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007713 goto error_open;
7714 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007715
7716 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7717 config->sample_rate = req_sample_rate;
7718 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7719 config->channel_mask = req_channel_mask;
7720 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7721 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007722 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007723
7724 out->sample_rate = config->sample_rate;
7725 out->channel_mask = config->channel_mask;
7726 out->format = config->format;
7727 if (is_hdmi) {
7728 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7729 out->config = pcm_config_hdmi_multi;
7730 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7731 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7732 out->config = pcm_config_mmap_playback;
7733 out->stream.start = out_start;
7734 out->stream.stop = out_stop;
7735 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7736 out->stream.get_mmap_position = out_get_mmap_position;
7737 } else {
7738 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7739 out->config = pcm_config_hifi;
7740 }
7741
7742 out->config.rate = out->sample_rate;
7743 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7744 if (is_hdmi) {
7745 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7746 audio_bytes_per_sample(out->format));
7747 }
7748 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007749 }
7750
Derek Chenf6318be2017-06-12 17:16:24 -04007751 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007752 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007753 /* extract car audio stream index */
7754 out->car_audio_stream =
7755 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7756 if (out->car_audio_stream < 0) {
7757 ALOGE("%s: invalid car audio stream %x",
7758 __func__, out->car_audio_stream);
7759 ret = -EINVAL;
7760 goto error_open;
7761 }
Derek Chen5f67a942020-02-24 23:08:13 -08007762 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007763 }
7764
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007765 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007766 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007767 if (!voice_extn_is_compress_voip_supported()) {
7768 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7769 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007770 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7771 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007772 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7773 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007774 out->volume_l = INVALID_OUT_VOLUME;
7775 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007776
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007777 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007778 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007779 uint32_t channel_count =
7780 audio_channel_count_from_out_mask(out->channel_mask);
7781 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7782 out->sample_rate, out->format,
7783 channel_count, false);
7784 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7785 if (frame_size != 0)
7786 out->config.period_size = buffer_size / frame_size;
7787 else
7788 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007789 }
7790 } else {
7791 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7792 voice_extn_compress_voip_is_active(out->dev)) &&
7793 (voice_extn_compress_voip_is_config_supported(config))) {
7794 ret = voice_extn_compress_voip_open_output_stream(out);
7795 if (ret != 0) {
7796 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7797 __func__, ret);
7798 goto error_open;
7799 }
Sujin Panicker19027262019-09-16 18:28:06 +05307800 } else {
7801 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7802 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007803 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007804 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007805 } else if (audio_is_linear_pcm(out->format) &&
7806 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7807 out->channel_mask = config->channel_mask;
7808 out->sample_rate = config->sample_rate;
7809 out->format = config->format;
7810 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7811 // does this change?
7812 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7813 out->config.rate = config->sample_rate;
7814 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7815 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7816 audio_bytes_per_sample(config->format));
7817 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007818 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307819 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307820 pthread_mutex_lock(&adev->lock);
7821 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7822 pthread_mutex_unlock(&adev->lock);
7823
7824 // reject offload during card offline to allow
7825 // fallback to s/w paths
7826 if (offline) {
7827 ret = -ENODEV;
7828 goto error_open;
7829 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007830
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007831 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7832 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7833 ALOGE("%s: Unsupported Offload information", __func__);
7834 ret = -EINVAL;
7835 goto error_open;
7836 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007837
Atul Khare3fa6e542017-08-09 00:56:17 +05307838 if (config->offload_info.format == 0)
7839 config->offload_info.format = config->format;
7840 if (config->offload_info.sample_rate == 0)
7841 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007842
Mingming Yin90310102013-11-13 16:57:00 -08007843 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307844 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007845 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007846 ret = -EINVAL;
7847 goto error_open;
7848 }
7849
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007850 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7851 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7852 (audio_extn_passthru_is_passthrough_stream(out)) &&
7853 !((config->sample_rate == 48000) ||
7854 (config->sample_rate == 96000) ||
7855 (config->sample_rate == 192000))) {
7856 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7857 __func__, config->sample_rate, config->offload_info.format);
7858 ret = -EINVAL;
7859 goto error_open;
7860 }
7861
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007862 out->compr_config.codec = (struct snd_codec *)
7863 calloc(1, sizeof(struct snd_codec));
7864
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007865 if (!out->compr_config.codec) {
7866 ret = -ENOMEM;
7867 goto error_open;
7868 }
7869
Dhananjay Kumarac341582017-02-23 23:42:25 +05307870 out->stream.pause = out_pause;
7871 out->stream.resume = out_resume;
7872 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307873 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307874 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007875 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307876 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007877 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307878 } else {
7879 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7880 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007881 }
vivek mehta446c3962015-09-14 10:57:35 -07007882
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307883 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7884 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007885#ifdef AUDIO_GKI_ENABLED
7886 /* out->compr_config.codec->reserved[1] is for flags */
7887 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7888#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307889 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007890#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307891 }
7892
vivek mehta446c3962015-09-14 10:57:35 -07007893 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007894 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007895 config->format == 0 && config->sample_rate == 0 &&
7896 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007897 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007898 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7899 } else {
7900 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7901 ret = -EEXIST;
7902 goto error_open;
7903 }
vivek mehta446c3962015-09-14 10:57:35 -07007904 }
7905
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007906 if (config->offload_info.channel_mask)
7907 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007908 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007909 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007910 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007911 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307912 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007913 ret = -EINVAL;
7914 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007915 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007916
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007917 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007918 out->sample_rate = config->offload_info.sample_rate;
7919
Mingming Yin3ee55c62014-08-04 14:23:35 -07007920 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007921
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307922 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307923 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307924 audio_extn_dolby_send_ddp_endp_params(adev);
7925 audio_extn_dolby_set_dmid(adev);
7926 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007927
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007928 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007929 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007930 out->compr_config.codec->bit_rate =
7931 config->offload_info.bit_rate;
7932 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307933 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007934 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307935 /* Update bit width only for non passthrough usecases.
7936 * For passthrough usecases, the output will always be opened @16 bit
7937 */
7938 if (!audio_extn_passthru_is_passthrough_stream(out))
7939 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307940
7941 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007942#ifdef AUDIO_GKI_ENABLED
7943 /* out->compr_config.codec->reserved[1] is for flags */
7944 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7945 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7946#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307947 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7948 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007949#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307950
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007951 /*TODO: Do we need to change it for passthrough */
7952 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007953
Manish Dewangana6fc5442015-08-24 20:30:31 +05307954 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7955 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307956 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307957 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307958 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7959 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307960
7961 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7962 AUDIO_FORMAT_PCM) {
7963
7964 /*Based on platform support, configure appropriate alsa format for corresponding
7965 *hal input format.
7966 */
7967 out->compr_config.codec->format = hal_format_to_alsa(
7968 config->offload_info.format);
7969
Ashish Jain83a6cc22016-06-28 14:34:17 +05307970 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307971 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307972 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307973
Dhananjay Kumarac341582017-02-23 23:42:25 +05307974 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307975 *hal input format and alsa format might differ based on platform support.
7976 */
7977 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307978 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307979
7980 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7981
Deeraj Soman93155a62019-09-30 19:00:37 +05307982 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7983 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7984 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7985 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7986 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307987
Ashish Jainf1eaa582016-05-23 20:54:24 +05307988 /* Check if alsa session is configured with the same format as HAL input format,
7989 * if not then derive correct fragment size needed to accomodate the
7990 * conversion of HAL input format to alsa format.
7991 */
7992 audio_extn_utils_update_direct_pcm_fragment_size(out);
7993
7994 /*if hal input and output fragment size is different this indicates HAL input format is
7995 *not same as the alsa format
7996 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307997 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307998 /*Allocate a buffer to convert input data to the alsa configured format.
7999 *size of convert buffer is equal to the size required to hold one fragment size
8000 *worth of pcm data, this is because flinger does not write more than fragment_size
8001 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308002 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8003 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308004 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8005 ret = -ENOMEM;
8006 goto error_open;
8007 }
8008 }
8009 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8010 out->compr_config.fragment_size =
8011 audio_extn_passthru_get_buffer_size(&config->offload_info);
8012 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8013 } else {
8014 out->compr_config.fragment_size =
8015 platform_get_compress_offload_buffer_size(&config->offload_info);
8016 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8017 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008018
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308019 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8020 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8021 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07008022 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308023 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008024
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308025 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8026 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8027 }
8028
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008029 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8030 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008031
Manish Dewangan69426c82017-01-30 17:35:36 +05308032 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8033 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8034 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8035 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8036 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8037 } else {
8038 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8039 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008040
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308041 memset(&out->channel_map_param, 0,
8042 sizeof(struct audio_out_channel_map_param));
8043
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008044 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308045 out->send_next_track_params = false;
8046 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008047 out->offload_state = OFFLOAD_STATE_IDLE;
8048 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008049 out->writeAt.tv_sec = 0;
8050 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008051
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008052 audio_extn_dts_create_state_notifier_node(out->usecase);
8053
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008054 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8055 __func__, config->offload_info.version,
8056 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308057
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308058 /* Check if DSD audio format is supported in codec
8059 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308060 */
8061
8062 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308063 (!platform_check_codec_dsd_support(adev->platform) ||
8064 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308065 ret = -EINVAL;
8066 goto error_open;
8067 }
8068
Ashish Jain5106d362016-05-11 19:23:33 +05308069 /* Disable gapless if any of the following is true
8070 * passthrough playback
8071 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308072 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308073 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308074 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308075 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008076 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308077 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308078 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308079 check_and_set_gapless_mode(adev, false);
8080 } else
8081 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008082
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308083 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008084 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8085 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308086 if (config->format == AUDIO_FORMAT_DSD) {
8087 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008088#ifdef AUDIO_GKI_ENABLED
8089 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8090 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8091#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308092 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008093#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308094 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008095
8096 create_offload_callback_thread(out);
8097
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008098 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008099 switch (config->sample_rate) {
8100 case 0:
8101 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8102 break;
8103 case 8000:
8104 case 16000:
8105 case 48000:
8106 out->sample_rate = config->sample_rate;
8107 break;
8108 default:
8109 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8110 config->sample_rate);
8111 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8112 ret = -EINVAL;
8113 goto error_open;
8114 }
8115 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8116 switch (config->channel_mask) {
8117 case AUDIO_CHANNEL_NONE:
8118 case AUDIO_CHANNEL_OUT_STEREO:
8119 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8120 break;
8121 default:
8122 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8123 config->channel_mask);
8124 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8125 ret = -EINVAL;
8126 goto error_open;
8127 }
8128 switch (config->format) {
8129 case AUDIO_FORMAT_DEFAULT:
8130 case AUDIO_FORMAT_PCM_16_BIT:
8131 out->format = AUDIO_FORMAT_PCM_16_BIT;
8132 break;
8133 default:
8134 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8135 config->format);
8136 config->format = AUDIO_FORMAT_PCM_16_BIT;
8137 ret = -EINVAL;
8138 goto error_open;
8139 }
8140
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308141 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008142 if (ret != 0) {
8143 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008144 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008145 goto error_open;
8146 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008147 } else if (is_single_device_type_equal(&out->device_list,
8148 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008149 switch (config->sample_rate) {
8150 case 0:
8151 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8152 break;
8153 case 8000:
8154 case 16000:
8155 case 48000:
8156 out->sample_rate = config->sample_rate;
8157 break;
8158 default:
8159 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8160 config->sample_rate);
8161 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8162 ret = -EINVAL;
8163 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008164 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008165 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8166 switch (config->channel_mask) {
8167 case AUDIO_CHANNEL_NONE:
8168 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8169 break;
8170 case AUDIO_CHANNEL_OUT_STEREO:
8171 out->channel_mask = config->channel_mask;
8172 break;
8173 default:
8174 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8175 config->channel_mask);
8176 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8177 ret = -EINVAL;
8178 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008179 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008180 switch (config->format) {
8181 case AUDIO_FORMAT_DEFAULT:
8182 out->format = AUDIO_FORMAT_PCM_16_BIT;
8183 break;
8184 case AUDIO_FORMAT_PCM_16_BIT:
8185 out->format = config->format;
8186 break;
8187 default:
8188 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8189 config->format);
8190 config->format = AUDIO_FORMAT_PCM_16_BIT;
8191 ret = -EINVAL;
8192 break;
8193 }
8194 if (ret != 0)
8195 goto error_open;
8196
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008197 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8198 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008199 out->config.rate = out->sample_rate;
8200 out->config.channels =
8201 audio_channel_count_from_out_mask(out->channel_mask);
8202 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008203 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008204 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308205 unsigned int channels = 0;
8206 /*Update config params to default if not set by the caller*/
8207 if (config->sample_rate == 0)
8208 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8209 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8210 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8211 if (config->format == AUDIO_FORMAT_DEFAULT)
8212 config->format = AUDIO_FORMAT_PCM_16_BIT;
8213
8214 channels = audio_channel_count_from_out_mask(out->channel_mask);
8215
Varun Balaraje49253e2017-07-06 19:48:56 +05308216 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8217 out->usecase = get_interactive_usecase(adev);
8218 out->config = pcm_config_low_latency;
8219 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308220 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008221 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8222 out->flags);
8223 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008224 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8225 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8226 out->config = pcm_config_mmap_playback;
8227 out->stream.start = out_start;
8228 out->stream.stop = out_stop;
8229 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8230 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308231 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8232 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008233 out->hal_output_suspend_supported =
8234 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8235 out->dynamic_pm_qos_config_supported =
8236 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8237 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008238 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8239 } else {
8240 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8241 //the mixer path will be a string similar to "low-latency-playback resume"
8242 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8243 strlcat(out->pm_qos_mixer_path,
8244 " resume", MAX_MIXER_PATH_LEN);
8245 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8246 out->pm_qos_mixer_path);
8247 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308248 out->config = pcm_config_low_latency;
8249 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8250 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8251 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308252 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8253 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8254 if (out->config.period_size <= 0) {
8255 ALOGE("Invalid configuration period size is not valid");
8256 ret = -EINVAL;
8257 goto error_open;
8258 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008259 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8260 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8261 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008262 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8263 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8264 out->config = pcm_config_haptics_audio;
8265 if (force_haptic_path)
8266 adev->haptics_config = pcm_config_haptics_audio;
8267 else
8268 adev->haptics_config = pcm_config_haptics;
8269
Meng Wangd08ce322020-04-02 08:59:20 +08008270 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008271 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8272
8273 if (force_haptic_path) {
8274 out->config.channels = 1;
8275 adev->haptics_config.channels = 1;
8276 } else
8277 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 -08008278 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008279 ret = audio_extn_auto_hal_open_output_stream(out);
8280 if (ret) {
8281 ALOGE("%s: Failed to open output stream for bus device", __func__);
8282 ret = -EINVAL;
8283 goto error_open;
8284 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308285 } else {
8286 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008287 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8288 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308289 }
8290 out->hal_ip_format = format = out->format;
8291 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8292 out->hal_op_format = pcm_format_to_hal(out->config.format);
8293 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8294 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008295 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308296 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308297 if (out->hal_ip_format != out->hal_op_format) {
8298 uint32_t buffer_size = out->config.period_size *
8299 format_to_bitwidth_table[out->hal_op_format] *
8300 out->config.channels;
8301 out->convert_buffer = calloc(1, buffer_size);
8302 if (out->convert_buffer == NULL){
8303 ALOGE("Allocation failed for convert buffer for size %d",
8304 out->compr_config.fragment_size);
8305 ret = -ENOMEM;
8306 goto error_open;
8307 }
8308 ALOGD("Convert buffer allocated of size %d", buffer_size);
8309 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008310 }
8311
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008312 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8313 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308314
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008315 /* TODO remove this hardcoding and check why width is zero*/
8316 if (out->bit_width == 0)
8317 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308318 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008319 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008320 &out->device_list, out->flags,
8321 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308322 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308323 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008324 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008325 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8326 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008327 if(adev->primary_output == NULL)
8328 adev->primary_output = out;
8329 else {
8330 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008331 ret = -EEXIST;
8332 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008333 }
8334 }
8335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008336 /* Check if this usecase is already existing */
8337 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008338 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8339 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008340 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008341 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008342 ret = -EEXIST;
8343 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008344 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008346 pthread_mutex_unlock(&adev->lock);
8347
8348 out->stream.common.get_sample_rate = out_get_sample_rate;
8349 out->stream.common.set_sample_rate = out_set_sample_rate;
8350 out->stream.common.get_buffer_size = out_get_buffer_size;
8351 out->stream.common.get_channels = out_get_channels;
8352 out->stream.common.get_format = out_get_format;
8353 out->stream.common.set_format = out_set_format;
8354 out->stream.common.standby = out_standby;
8355 out->stream.common.dump = out_dump;
8356 out->stream.common.set_parameters = out_set_parameters;
8357 out->stream.common.get_parameters = out_get_parameters;
8358 out->stream.common.add_audio_effect = out_add_audio_effect;
8359 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8360 out->stream.get_latency = out_get_latency;
8361 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008362#ifdef NO_AUDIO_OUT
8363 out->stream.write = out_write_for_no_output;
8364#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008365 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008366#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008367 out->stream.get_render_position = out_get_render_position;
8368 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008369 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008370
Haynes Mathew George16081042017-05-31 17:16:49 -07008371 if (out->realtime)
8372 out->af_period_multiplier = af_period_multiplier;
8373 else
8374 out->af_period_multiplier = 1;
8375
Andy Hunga1f48fa2019-07-01 18:14:53 -07008376 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8377
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008378 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008379 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008380 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008381
8382 config->format = out->stream.common.get_format(&out->stream.common);
8383 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8384 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308385 register_format(out->format, out->supported_formats);
8386 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8387 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008388
Aalique Grahame22e49102018-12-18 14:23:57 -08008389 out->error_log = error_log_create(
8390 ERROR_LOG_ENTRIES,
8391 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8392
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308393 /*
8394 By locking output stream before registering, we allow the callback
8395 to update stream's state only after stream's initial state is set to
8396 adev state.
8397 */
8398 lock_output_stream(out);
8399 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8400 pthread_mutex_lock(&adev->lock);
8401 out->card_status = adev->card_status;
8402 pthread_mutex_unlock(&adev->lock);
8403 pthread_mutex_unlock(&out->lock);
8404
Aalique Grahame22e49102018-12-18 14:23:57 -08008405 stream_app_type_cfg_init(&out->app_type_cfg);
8406
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008407 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308408 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008409 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008410
8411 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8412 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8413 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008414 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308415 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008416 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008417 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308418 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8419 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008420 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8421 out->usecase, PCM_PLAYBACK);
8422 hdlr_stream_cfg.flags = out->flags;
8423 hdlr_stream_cfg.type = PCM_PLAYBACK;
8424 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8425 &hdlr_stream_cfg);
8426 if (ret) {
8427 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8428 out->adsp_hdlr_stream_handle = NULL;
8429 }
8430 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308431 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8432 is_direct_passthough, false);
8433 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8434 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008435 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008436 if (ret < 0) {
8437 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8438 out->ip_hdlr_handle = NULL;
8439 }
8440 }
Derek Chenf939fb72018-11-13 13:34:41 -08008441
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008442 ret = io_streams_map_insert(adev, &out->stream.common,
8443 out->handle, AUDIO_PATCH_HANDLE_NONE);
8444 if (ret != 0)
8445 goto error_open;
8446
Derek Chenf939fb72018-11-13 13:34:41 -08008447 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8448 calloc(1, sizeof(streams_output_ctxt_t));
8449 if (out_ctxt == NULL) {
8450 ALOGE("%s fail to allocate output ctxt", __func__);
8451 ret = -ENOMEM;
8452 goto error_open;
8453 }
8454 out_ctxt->output = out;
8455
8456 pthread_mutex_lock(&adev->lock);
8457 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8458 pthread_mutex_unlock(&adev->lock);
8459
Eric Laurent994a6932013-07-17 11:51:42 -07008460 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008461 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008462
8463error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308464 if (out->convert_buffer)
8465 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008466 free(out);
8467 *stream_out = NULL;
8468 ALOGD("%s: exit: ret %d", __func__, ret);
8469 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008470}
8471
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308472void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008473 struct audio_stream_out *stream)
8474{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008475 struct stream_out *out = (struct stream_out *)stream;
8476 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008477 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008478
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008479 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308480
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008481 io_streams_map_remove(adev, out->handle);
8482
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308483 // must deregister from sndmonitor first to prevent races
8484 // between the callback and close_stream
8485 audio_extn_snd_mon_unregister_listener(out);
8486
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008487 /* close adsp hdrl session before standby */
8488 if (out->adsp_hdlr_stream_handle) {
8489 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8490 if (ret)
8491 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8492 out->adsp_hdlr_stream_handle = NULL;
8493 }
8494
Manish Dewangan21a850a2017-08-14 12:03:55 +05308495 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008496 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8497 out->ip_hdlr_handle = NULL;
8498 }
8499
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008500 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308501 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008502 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308503 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308504 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008505 if(ret != 0)
8506 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8507 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008508 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008509 out_standby(&stream->common);
8510
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008511 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008512 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008513 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008514 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008515 if (out->compr_config.codec != NULL)
8516 free(out->compr_config.codec);
8517 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008518
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308519 out->a2dp_compress_mute = false;
8520
Varun Balaraje49253e2017-07-06 19:48:56 +05308521 if (is_interactive_usecase(out->usecase))
8522 free_interactive_usecase(adev, out->usecase);
8523
Ashish Jain83a6cc22016-06-28 14:34:17 +05308524 if (out->convert_buffer != NULL) {
8525 free(out->convert_buffer);
8526 out->convert_buffer = NULL;
8527 }
8528
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008529 if (adev->voice_tx_output == out)
8530 adev->voice_tx_output = NULL;
8531
Aalique Grahame22e49102018-12-18 14:23:57 -08008532 error_log_destroy(out->error_log);
8533 out->error_log = NULL;
8534
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308535 if (adev->primary_output == out)
8536 adev->primary_output = NULL;
8537
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008538 pthread_cond_destroy(&out->cond);
8539 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008540
8541 pthread_mutex_lock(&adev->lock);
8542 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8543 if (out_ctxt != NULL) {
8544 list_remove(&out_ctxt->list);
8545 free(out_ctxt);
8546 } else {
8547 ALOGW("%s, output stream already closed", __func__);
8548 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008549 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008550 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008551 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008552}
8553
8554static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8555{
8556 struct audio_device *adev = (struct audio_device *)dev;
8557 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008558 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008559 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008560 int ret;
8561 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008562 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008563 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008564 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008565
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008566 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008567 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008568
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308569 if (!parms)
8570 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308571
Derek Chen6f293672019-04-01 01:40:24 -07008572 /* notify adev and input/output streams on the snd card status */
8573 adev_snd_mon_cb((void *)adev, parms);
8574
8575 list_for_each(node, &adev->active_outputs_list) {
8576 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8577 streams_output_ctxt_t,
8578 list);
8579 out_snd_mon_cb((void *)out_ctxt->output, parms);
8580 }
8581
8582 list_for_each(node, &adev->active_inputs_list) {
8583 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8584 streams_input_ctxt_t,
8585 list);
8586 in_snd_mon_cb((void *)in_ctxt->input, parms);
8587 }
8588
Zhou Songd6d71752019-05-21 18:08:51 +08008589 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308590 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8591 if (ret >= 0) {
8592 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008593 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308594 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008595 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308596 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008597 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008598 }
8599 }
8600
8601 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8602 if (ret>=0) {
8603 if (!strncmp(value, "false", 5) &&
8604 audio_extn_a2dp_source_is_suspended()) {
8605 struct audio_usecase *usecase;
8606 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008607 list_for_each(node, &adev->usecase_list) {
8608 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008609 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008610 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008611 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008612 reassign_device_list(&usecase->stream.in->device_list,
8613 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008614 select_devices(adev, usecase->id);
8615 }
Zhou Songd6d71752019-05-21 18:08:51 +08008616 }
8617 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308618 }
8619
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008620 status = voice_set_parameters(adev, parms);
8621 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008622 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008623
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008624 status = platform_set_parameters(adev->platform, parms);
8625 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008626 goto done;
8627
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008628 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8629 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008630 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008631 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8632 adev->bluetooth_nrec = true;
8633 else
8634 adev->bluetooth_nrec = false;
8635 }
8636
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008637 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8638 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008639 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8640 adev->screen_off = false;
8641 else
8642 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008643 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008644 }
8645
Eric Laurent4b084132018-10-19 17:33:43 -07008646 ret = str_parms_get_int(parms, "rotation", &val);
8647 if (ret >= 0) {
8648 bool reverse_speakers = false;
8649 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8650 switch (val) {
8651 // FIXME: note that the code below assumes that the speakers are in the correct placement
8652 // relative to the user when the device is rotated 90deg from its default rotation. This
8653 // assumption is device-specific, not platform-specific like this code.
8654 case 270:
8655 reverse_speakers = true;
8656 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8657 break;
8658 case 0:
8659 case 180:
8660 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8661 break;
8662 case 90:
8663 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8664 break;
8665 default:
8666 ALOGE("%s: unexpected rotation of %d", __func__, val);
8667 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008668 }
Eric Laurent4b084132018-10-19 17:33:43 -07008669 if (status == 0) {
8670 // check and set swap
8671 // - check if orientation changed and speaker active
8672 // - set rotation and cache the rotation value
8673 adev->camera_orientation =
8674 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8675 if (!audio_extn_is_maxx_audio_enabled())
8676 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8677 }
8678 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008679
Mingming Yin514a8bc2014-07-29 15:22:21 -07008680 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8681 if (ret >= 0) {
8682 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8683 adev->bt_wb_speech_enabled = true;
8684 else
8685 adev->bt_wb_speech_enabled = false;
8686 }
8687
Zhou Song12c29502019-03-16 10:37:18 +08008688 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8689 if (ret >= 0) {
8690 val = atoi(value);
8691 adev->swb_speech_mode = val;
8692 }
8693
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008694 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8695 if (ret >= 0) {
8696 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308697 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008698 if (audio_is_output_device(val) &&
8699 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008700 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008701 platform_get_controller_stream_from_params(parms, &controller, &stream);
8702 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8703 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008704 if (ret < 0) {
8705 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308706 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008707 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008708 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308709 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008710 /*
8711 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8712 * Per AudioPolicyManager, USB device is higher priority than WFD.
8713 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8714 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8715 * starting voice call on USB
8716 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008717 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308718 if (ret >= 0)
8719 audio_extn_usb_add_device(device, atoi(value));
8720
Zhou Song6f862822017-11-06 17:27:57 +08008721 if (!audio_extn_usb_is_tunnel_supported()) {
8722 ALOGV("detected USB connect .. disable proxy");
8723 adev->allow_afe_proxy_usage = false;
8724 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008725 }
8726 }
8727
8728 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8729 if (ret >= 0) {
8730 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308731 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008732 /*
8733 * The HDMI / Displayport disconnect handling has been moved to
8734 * audio extension to ensure that its parameters are not
8735 * invalidated prior to updating sysfs of the disconnect event
8736 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8737 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308738 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008739 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308740 if (ret >= 0)
8741 audio_extn_usb_remove_device(device, atoi(value));
8742
Zhou Song6f862822017-11-06 17:27:57 +08008743 if (!audio_extn_usb_is_tunnel_supported()) {
8744 ALOGV("detected USB disconnect .. enable proxy");
8745 adev->allow_afe_proxy_usage = true;
8746 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008747 }
8748 }
8749
Aalique Grahame22e49102018-12-18 14:23:57 -08008750 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008751 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008752
8753 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008754 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308755 struct audio_usecase *usecase;
8756 struct listnode *node;
8757 list_for_each(node, &adev->usecase_list) {
8758 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008759 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8760 continue;
8761
8762 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308763 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008764 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308765 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008766 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308767 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308768 ALOGD("Switching to speaker and muting the stream before select_devices");
8769 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308770 //force device switch to re configure encoder
8771 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308772 ALOGD("Unmuting the stream after select_devices");
8773 usecase->stream.out->a2dp_compress_mute = false;
8774 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 +05308775 audio_extn_a2dp_set_handoff_mode(false);
8776 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308777 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308778 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8779 usecase->stream.out->a2dp_compress_mute) {
8780 pthread_mutex_unlock(&adev->lock);
8781 lock_output_stream(usecase->stream.out);
8782 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008783 reassign_device_list(&usecase->stream.out->device_list,
8784 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308785 check_a2dp_restore_l(adev, usecase->stream.out, true);
8786 pthread_mutex_unlock(&usecase->stream.out->lock);
8787 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308788 }
8789 }
8790 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008791
8792 //handle vr audio setparam
8793 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8794 value, sizeof(value));
8795 if (ret >= 0) {
8796 ALOGI("Setting vr mode to be %s", value);
8797 if (!strncmp(value, "true", 4)) {
8798 adev->vr_audio_mode_enabled = true;
8799 ALOGI("Setting vr mode to true");
8800 } else if (!strncmp(value, "false", 5)) {
8801 adev->vr_audio_mode_enabled = false;
8802 ALOGI("Setting vr mode to false");
8803 } else {
8804 ALOGI("wrong vr mode set");
8805 }
8806 }
8807
Eric Laurent4b084132018-10-19 17:33:43 -07008808 //FIXME: to be replaced by proper video capture properties API
8809 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8810 if (ret >= 0) {
8811 int camera_facing = CAMERA_FACING_BACK;
8812 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8813 camera_facing = CAMERA_FACING_FRONT;
8814 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8815 camera_facing = CAMERA_FACING_BACK;
8816 else {
8817 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8818 goto done;
8819 }
8820 adev->camera_orientation =
8821 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8822 struct audio_usecase *usecase;
8823 struct listnode *node;
8824 list_for_each(node, &adev->usecase_list) {
8825 usecase = node_to_item(node, struct audio_usecase, list);
8826 struct stream_in *in = usecase->stream.in;
8827 if (usecase->type == PCM_CAPTURE && in != NULL &&
8828 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8829 select_devices(adev, in->usecase);
8830 }
8831 }
8832 }
8833
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308834 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008835done:
8836 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008837 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308838error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008839 ALOGV("%s: exit with code(%d)", __func__, status);
8840 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008841}
8842
8843static char* adev_get_parameters(const struct audio_hw_device *dev,
8844 const char *keys)
8845{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308846 ALOGD("%s:%s", __func__, keys);
8847
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008848 struct audio_device *adev = (struct audio_device *)dev;
8849 struct str_parms *reply = str_parms_create();
8850 struct str_parms *query = str_parms_create_str(keys);
8851 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308852 char value[256] = {0};
8853 int ret = 0;
8854
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008855 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008856 if (reply) {
8857 str_parms_destroy(reply);
8858 }
8859 if (query) {
8860 str_parms_destroy(query);
8861 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008862 ALOGE("adev_get_parameters: failed to create query or reply");
8863 return NULL;
8864 }
8865
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008866 //handle vr audio getparam
8867
8868 ret = str_parms_get_str(query,
8869 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8870 value, sizeof(value));
8871
8872 if (ret >= 0) {
8873 bool vr_audio_enabled = false;
8874 pthread_mutex_lock(&adev->lock);
8875 vr_audio_enabled = adev->vr_audio_mode_enabled;
8876 pthread_mutex_unlock(&adev->lock);
8877
8878 ALOGI("getting vr mode to %d", vr_audio_enabled);
8879
8880 if (vr_audio_enabled) {
8881 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8882 "true");
8883 goto exit;
8884 } else {
8885 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8886 "false");
8887 goto exit;
8888 }
8889 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008890
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008891 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008892 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008893 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008894 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008895 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08008896 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308897 pthread_mutex_unlock(&adev->lock);
8898
Naresh Tannirud7205b62014-06-20 02:54:48 +05308899exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008900 str = str_parms_to_str(reply);
8901 str_parms_destroy(query);
8902 str_parms_destroy(reply);
8903
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308904 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008905 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008906}
8907
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008908static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008909{
8910 return 0;
8911}
8912
8913static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8914{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008915 int ret;
8916 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008917
8918 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8919
Haynes Mathew George5191a852013-09-11 14:19:36 -07008920 pthread_mutex_lock(&adev->lock);
8921 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008922 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008923 pthread_mutex_unlock(&adev->lock);
8924 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008925}
8926
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008927static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8928 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008929{
8930 return -ENOSYS;
8931}
8932
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008933static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8934 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008935{
8936 return -ENOSYS;
8937}
8938
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008939static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8940 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008941{
8942 return -ENOSYS;
8943}
8944
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008945static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8946 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008947{
8948 return -ENOSYS;
8949}
8950
8951static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8952{
8953 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008954 struct listnode *node;
8955 struct audio_usecase *usecase = NULL;
8956 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008957
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008958 pthread_mutex_lock(&adev->lock);
8959 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05308960 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
8961 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008962 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05308963 if( mode == AUDIO_MODE_CALL_SCREEN ){
8964 adev->current_call_output = adev->primary_output;
8965 voice_start_call(adev);
8966 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008967 (mode == AUDIO_MODE_NORMAL ||
8968 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008969 list_for_each(node, &adev->usecase_list) {
8970 usecase = node_to_item(node, struct audio_usecase, list);
8971 if (usecase->type == VOICE_CALL)
8972 break;
8973 }
8974 if (usecase &&
8975 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8976 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8977 true);
8978 if (ret != 0) {
8979 /* default service interval was successfully updated,
8980 reopen USB backend with new service interval */
8981 check_usecases_codec_backend(adev,
8982 usecase,
8983 usecase->out_snd_device);
8984 }
8985 }
8986
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008987 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008988 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008989 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008990 // restore device for other active usecases after stop call
8991 list_for_each(node, &adev->usecase_list) {
8992 usecase = node_to_item(node, struct audio_usecase, list);
8993 select_devices(adev, usecase->id);
8994 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008995 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008996 }
8997 pthread_mutex_unlock(&adev->lock);
8998 return 0;
8999}
9000
9001static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9002{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009003 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009004 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009005
9006 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009007 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009008 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009009
Derek Chend2530072014-11-24 12:39:14 -08009010 if (adev->ext_hw_plugin)
9011 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009012
9013 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009014 pthread_mutex_unlock(&adev->lock);
9015
9016 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009017}
9018
9019static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9020{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009021 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009022 return 0;
9023}
9024
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009025static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009026 const struct audio_config *config)
9027{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009028 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009029
Aalique Grahame22e49102018-12-18 14:23:57 -08009030 /* Don't know if USB HIFI in this context so use true to be conservative */
9031 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9032 true /*is_usb_hifi */) != 0)
9033 return 0;
9034
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009035 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9036 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009037}
9038
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009039static bool adev_input_allow_hifi_record(struct audio_device *adev,
9040 audio_devices_t devices,
9041 audio_input_flags_t flags,
9042 audio_source_t source) {
9043 const bool allowed = true;
9044
9045 if (!audio_is_usb_in_device(devices))
9046 return !allowed;
9047
9048 switch (flags) {
9049 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009050 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009051 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9052 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009053 default:
9054 return !allowed;
9055 }
9056
9057 switch (source) {
9058 case AUDIO_SOURCE_DEFAULT:
9059 case AUDIO_SOURCE_MIC:
9060 case AUDIO_SOURCE_UNPROCESSED:
9061 break;
9062 default:
9063 return !allowed;
9064 }
9065
9066 switch (adev->mode) {
9067 case 0:
9068 break;
9069 default:
9070 return !allowed;
9071 }
9072
9073 return allowed;
9074}
9075
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009076static int adev_update_voice_comm_input_stream(struct stream_in *in,
9077 struct audio_config *config)
9078{
9079 bool valid_rate = (config->sample_rate == 8000 ||
9080 config->sample_rate == 16000 ||
9081 config->sample_rate == 32000 ||
9082 config->sample_rate == 48000);
9083 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9084
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009085 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009086 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009087 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9088 in->config = default_pcm_config_voip_copp;
9089 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9090 DEFAULT_VOIP_BUF_DURATION_MS,
9091 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009092 } else {
9093 ALOGW("%s No valid input in voip, use defaults"
9094 "sample rate %u, channel mask 0x%X",
9095 __func__, config->sample_rate, in->channel_mask);
9096 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009097 in->config.rate = config->sample_rate;
9098 in->sample_rate = config->sample_rate;
9099 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009100 //XXX needed for voice_extn_compress_voip_open_input_stream
9101 in->config.rate = config->sample_rate;
9102 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309103 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009104 voice_extn_compress_voip_is_active(in->dev)) &&
9105 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9106 valid_rate && valid_ch) {
9107 voice_extn_compress_voip_open_input_stream(in);
9108 // update rate entries to match config from AF
9109 in->config.rate = config->sample_rate;
9110 in->sample_rate = config->sample_rate;
9111 } else {
9112 ALOGW("%s compress voip not active, use defaults", __func__);
9113 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009114 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009115 return 0;
9116}
9117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009118static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009119 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009120 audio_devices_t devices,
9121 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009122 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309123 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009124 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009125 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009126{
9127 struct audio_device *adev = (struct audio_device *)dev;
9128 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009129 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009130 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009131 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309132 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009133 bool is_usb_dev = audio_is_usb_in_device(devices);
9134 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9135 devices,
9136 flags,
9137 source);
Andy Hung94320602018-10-29 18:31:12 -07009138 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9139 " sample_rate %u, channel_mask %#x, format %#x",
9140 __func__, flags, is_usb_dev, may_use_hifi_record,
9141 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309142
kunleizdff872d2018-08-20 14:40:33 +08009143 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009144 is_usb_dev = false;
9145 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9146 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9147 __func__, devices);
9148 }
9149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009150 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009151
9152 if (!(is_usb_dev && may_use_hifi_record)) {
9153 if (config->sample_rate == 0)
9154 config->sample_rate = 48000;
9155 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9156 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9157 if (config->format == AUDIO_FORMAT_DEFAULT)
9158 config->format = AUDIO_FORMAT_PCM_16_BIT;
9159
9160 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9161
Aalique Grahame22e49102018-12-18 14:23:57 -08009162 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9163 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009164 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309165 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009166
Rahul Sharma99770982019-03-06 17:05:26 +05309167 pthread_mutex_lock(&adev->lock);
9168 if (in_get_stream(adev, handle) != NULL) {
9169 ALOGW("%s, input stream already opened", __func__);
9170 ret = -EEXIST;
9171 }
9172 pthread_mutex_unlock(&adev->lock);
9173 if (ret)
9174 return ret;
9175
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009176 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009177
9178 if (!in) {
9179 ALOGE("failed to allocate input stream");
9180 return -ENOMEM;
9181 }
9182
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309183 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309184 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9185 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009186 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009187 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009189 in->stream.common.get_sample_rate = in_get_sample_rate;
9190 in->stream.common.set_sample_rate = in_set_sample_rate;
9191 in->stream.common.get_buffer_size = in_get_buffer_size;
9192 in->stream.common.get_channels = in_get_channels;
9193 in->stream.common.get_format = in_get_format;
9194 in->stream.common.set_format = in_set_format;
9195 in->stream.common.standby = in_standby;
9196 in->stream.common.dump = in_dump;
9197 in->stream.common.set_parameters = in_set_parameters;
9198 in->stream.common.get_parameters = in_get_parameters;
9199 in->stream.common.add_audio_effect = in_add_audio_effect;
9200 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9201 in->stream.set_gain = in_set_gain;
9202 in->stream.read = in_read;
9203 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009204 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309205 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009206 in->stream.set_microphone_direction = in_set_microphone_direction;
9207 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009208 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009209
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009210 list_init(&in->device_list);
9211 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009212 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009213 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009214 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009215 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009216 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009217 in->bit_width = 16;
9218 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009219 in->direction = MIC_DIRECTION_UNSPECIFIED;
9220 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009221 list_init(&in->aec_list);
9222 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009223 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009224
Andy Hung94320602018-10-29 18:31:12 -07009225 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009226 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9227 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9228 /* Force channel config requested to mono if incall
9229 record is being requested for only uplink/downlink */
9230 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9231 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9232 ret = -EINVAL;
9233 goto err_open;
9234 }
9235 }
9236
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009237 if (is_usb_dev && may_use_hifi_record) {
9238 /* HiFi record selects an appropriate format, channel, rate combo
9239 depending on sink capabilities*/
9240 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9241 &config->format,
9242 &in->supported_formats[0],
9243 MAX_SUPPORTED_FORMATS,
9244 &config->channel_mask,
9245 &in->supported_channel_masks[0],
9246 MAX_SUPPORTED_CHANNEL_MASKS,
9247 &config->sample_rate,
9248 &in->supported_sample_rates[0],
9249 MAX_SUPPORTED_SAMPLE_RATES);
9250 if (ret != 0) {
9251 ret = -EINVAL;
9252 goto err_open;
9253 }
9254 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009255 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309256 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309257 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9258 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9259 in->config.format = PCM_FORMAT_S32_LE;
9260 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309261 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9262 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9263 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9264 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9265 bool ret_error = false;
9266 in->bit_width = 24;
9267 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9268 from HAL is 24_packed and 8_24
9269 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9270 24_packed return error indicating supported format is 24_packed
9271 *> In case of any other source requesting 24 bit or float return error
9272 indicating format supported is 16 bit only.
9273
9274 on error flinger will retry with supported format passed
9275 */
9276 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9277 (source != AUDIO_SOURCE_CAMCORDER)) {
9278 config->format = AUDIO_FORMAT_PCM_16_BIT;
9279 if (config->sample_rate > 48000)
9280 config->sample_rate = 48000;
9281 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009282 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9283 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309284 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9285 ret_error = true;
9286 }
9287
9288 if (ret_error) {
9289 ret = -EINVAL;
9290 goto err_open;
9291 }
9292 }
9293
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009294 in->channel_mask = config->channel_mask;
9295 in->format = config->format;
9296
9297 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309298
9299 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9300 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9301 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9302 else {
9303 ret = -EINVAL;
9304 goto err_open;
9305 }
9306 }
9307
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009308 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309309 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9310 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009311 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9312 is_low_latency = true;
9313#if LOW_LATENCY_CAPTURE_USE_CASE
9314 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9315#endif
9316 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009317 if (!in->realtime) {
9318 in->config = pcm_config_audio_capture;
9319 frame_size = audio_stream_in_frame_size(&in->stream);
9320 buffer_size = get_input_buffer_size(config->sample_rate,
9321 config->format,
9322 channel_count,
9323 is_low_latency);
9324 in->config.period_size = buffer_size / frame_size;
9325 in->config.rate = config->sample_rate;
9326 in->af_period_multiplier = 1;
9327 } else {
9328 // period size is left untouched for rt mode playback
9329 in->config = pcm_config_audio_capture_rt;
9330 in->af_period_multiplier = af_period_multiplier;
9331 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009332 }
9333
9334 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9335 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9336 in->realtime = 0;
9337 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9338 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009339 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009340 in->stream.start = in_start;
9341 in->stream.stop = in_stop;
9342 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9343 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009344 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009345 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009346 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9347 in->config = pcm_config_audio_capture;
9348 frame_size = audio_stream_in_frame_size(&in->stream);
9349 buffer_size = get_input_buffer_size(config->sample_rate,
9350 config->format,
9351 channel_count,
9352 false /*is_low_latency*/);
9353 in->config.period_size = buffer_size / frame_size;
9354 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009355 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009356 switch (config->format) {
9357 case AUDIO_FORMAT_PCM_32_BIT:
9358 in->bit_width = 32;
9359 break;
9360 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9361 case AUDIO_FORMAT_PCM_8_24_BIT:
9362 in->bit_width = 24;
9363 break;
9364 default:
9365 in->bit_width = 16;
9366 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009367 } else if (is_single_device_type_equal(&in->device_list,
9368 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9369 is_single_device_type_equal(&in->device_list,
9370 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009371 if (config->sample_rate == 0)
9372 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9373 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9374 config->sample_rate != 8000) {
9375 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9376 ret = -EINVAL;
9377 goto err_open;
9378 }
9379 if (config->format == AUDIO_FORMAT_DEFAULT)
9380 config->format = AUDIO_FORMAT_PCM_16_BIT;
9381 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9382 config->format = AUDIO_FORMAT_PCM_16_BIT;
9383 ret = -EINVAL;
9384 goto err_open;
9385 }
9386
9387 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009388 if (adev->ha_proxy_enable &&
9389 is_single_device_type_equal(&in->device_list,
9390 AUDIO_DEVICE_IN_TELEPHONY_RX))
9391 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009392 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009393 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009394 in->af_period_multiplier = 1;
9395 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9396 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9397 (config->sample_rate == 8000 ||
9398 config->sample_rate == 16000 ||
9399 config->sample_rate == 32000 ||
9400 config->sample_rate == 48000) &&
9401 channel_count == 1) {
9402 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9403 in->config = pcm_config_audio_capture;
9404 frame_size = audio_stream_in_frame_size(&in->stream);
9405 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9406 config->sample_rate,
9407 config->format,
9408 channel_count, false /*is_low_latency*/);
9409 in->config.period_size = buffer_size / frame_size;
9410 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9411 in->config.rate = config->sample_rate;
9412 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009413 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309414 int ret_val;
9415 pthread_mutex_lock(&adev->lock);
9416 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9417 in, config, &channel_mask_updated);
9418 pthread_mutex_unlock(&adev->lock);
9419
9420 if (!ret_val) {
9421 if (channel_mask_updated == true) {
9422 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9423 __func__, config->channel_mask);
9424 ret = -EINVAL;
9425 goto err_open;
9426 }
9427 ALOGD("%s: created multi-channel session succesfully",__func__);
9428 } else if (audio_extn_compr_cap_enabled() &&
9429 audio_extn_compr_cap_format_supported(config->format) &&
9430 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9431 audio_extn_compr_cap_init(in);
9432 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309433 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309434 if (ret)
9435 goto err_open;
9436 } else {
9437 in->config = pcm_config_audio_capture;
9438 in->config.rate = config->sample_rate;
9439 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309440 in->format = config->format;
9441 frame_size = audio_stream_in_frame_size(&in->stream);
9442 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009443 config->format,
9444 channel_count,
9445 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009446 /* prevent division-by-zero */
9447 if (frame_size == 0) {
9448 ALOGE("%s: Error frame_size==0", __func__);
9449 ret = -EINVAL;
9450 goto err_open;
9451 }
9452
Revathi Uddarajud2634032017-12-07 14:42:34 +05309453 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009454 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009455
Revathi Uddarajud2634032017-12-07 14:42:34 +05309456 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9457 /* optionally use VOIP usecase depending on config(s) */
9458 ret = adev_update_voice_comm_input_stream(in, config);
9459 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009460
Revathi Uddarajud2634032017-12-07 14:42:34 +05309461 if (ret) {
9462 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9463 goto err_open;
9464 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009465 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309466
9467 /* assign concurrent capture usecase if record has to caried out from
9468 * actual hardware input source */
9469 if (audio_extn_is_concurrent_capture_enabled() &&
9470 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309471 /* Acquire lock to avoid two concurrent use cases initialized to
9472 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009473
Samyak Jainc37062f2019-04-25 18:41:06 +05309474 if (in->usecase == USECASE_AUDIO_RECORD) {
9475 pthread_mutex_lock(&adev->lock);
9476 if (!(adev->pcm_record_uc_state)) {
9477 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9478 adev->pcm_record_uc_state = 1;
9479 pthread_mutex_unlock(&adev->lock);
9480 } else {
9481 pthread_mutex_unlock(&adev->lock);
9482 /* Assign compress record use case for second record */
9483 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9484 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9485 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9486 if (audio_extn_cin_applicable_stream(in)) {
9487 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309488 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309489 if (ret)
9490 goto err_open;
9491 }
9492 }
9493 }
kunleiz28c73e72019-03-27 17:24:04 +08009494 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009495 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309496 if (audio_extn_ssr_get_stream() != in)
9497 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009498
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009499 in->sample_rate = in->config.rate;
9500
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309501 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9502 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009503 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009504 in->sample_rate, in->bit_width,
9505 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309506 register_format(in->format, in->supported_formats);
9507 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9508 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309509
Aalique Grahame22e49102018-12-18 14:23:57 -08009510 in->error_log = error_log_create(
9511 ERROR_LOG_ENTRIES,
9512 1000000000 /* aggregate consecutive identical errors within one second */);
9513
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009514 /* This stream could be for sound trigger lab,
9515 get sound trigger pcm if present */
9516 audio_extn_sound_trigger_check_and_get_session(in);
9517
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309518 lock_input_stream(in);
9519 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9520 pthread_mutex_lock(&adev->lock);
9521 in->card_status = adev->card_status;
9522 pthread_mutex_unlock(&adev->lock);
9523 pthread_mutex_unlock(&in->lock);
9524
Aalique Grahame22e49102018-12-18 14:23:57 -08009525 stream_app_type_cfg_init(&in->app_type_cfg);
9526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009527 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009528
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009529 ret = io_streams_map_insert(adev, &in->stream.common,
9530 handle, AUDIO_PATCH_HANDLE_NONE);
9531 if (ret != 0)
9532 goto err_open;
9533
Derek Chenf939fb72018-11-13 13:34:41 -08009534 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9535 calloc(1, sizeof(streams_input_ctxt_t));
9536 if (in_ctxt == NULL) {
9537 ALOGE("%s fail to allocate input ctxt", __func__);
9538 ret = -ENOMEM;
9539 goto err_open;
9540 }
9541 in_ctxt->input = in;
9542
9543 pthread_mutex_lock(&adev->lock);
9544 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9545 pthread_mutex_unlock(&adev->lock);
9546
Eric Laurent994a6932013-07-17 11:51:42 -07009547 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009548 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009549
9550err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309551 if (in->usecase == USECASE_AUDIO_RECORD) {
9552 pthread_mutex_lock(&adev->lock);
9553 adev->pcm_record_uc_state = 0;
9554 pthread_mutex_unlock(&adev->lock);
9555 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009556 free(in);
9557 *stream_in = NULL;
9558 return ret;
9559}
9560
9561static void adev_close_input_stream(struct audio_hw_device *dev,
9562 struct audio_stream_in *stream)
9563{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009564 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009565 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009566 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309567
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309568 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009569
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009570 if (in == NULL) {
9571 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9572 return;
9573 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009574 io_streams_map_remove(adev, in->capture_handle);
9575
kunleiz70e57612018-12-28 17:50:23 +08009576 /* must deregister from sndmonitor first to prevent races
9577 * between the callback and close_stream
9578 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309579 audio_extn_snd_mon_unregister_listener(stream);
9580
kunleiz70e57612018-12-28 17:50:23 +08009581 /* Disable echo reference if there are no active input, hfp call
9582 * and sound trigger while closing input stream
9583 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009584 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009585 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009586 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9587 struct listnode out_devices;
9588 list_init(&out_devices);
9589 platform_set_echo_reference(adev, false, &out_devices);
9590 } else
kunleiz70e57612018-12-28 17:50:23 +08009591 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309592
Weiyin Jiang2995f662019-04-17 14:25:12 +08009593 error_log_destroy(in->error_log);
9594 in->error_log = NULL;
9595
Pallavid7c7a272018-01-16 11:22:55 +05309596
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009597 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309598 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009599 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309600 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009601 if (ret != 0)
9602 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9603 __func__, ret);
9604 } else
9605 in_standby(&stream->common);
9606
Revathi Uddarajud2634032017-12-07 14:42:34 +05309607 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309608 if (in->usecase == USECASE_AUDIO_RECORD) {
9609 adev->pcm_record_uc_state = 0;
9610 }
9611
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009612 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9613 adev->enable_voicerx = false;
9614 }
9615
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009616 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009617 audio_extn_ssr_deinit();
9618 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009619
Garmond Leunge2433c32017-09-28 21:51:22 -07009620 if (audio_extn_ffv_get_stream() == in) {
9621 audio_extn_ffv_stream_deinit();
9622 }
9623
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309624 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009625 audio_extn_compr_cap_format_supported(in->config.format))
9626 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309627
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309628 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309629 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009630
Mingming Yinfd7607b2016-01-22 12:48:44 -08009631 if (in->is_st_session) {
9632 ALOGV("%s: sound trigger pcm stop lab", __func__);
9633 audio_extn_sound_trigger_stop_lab(in);
9634 }
Derek Chenf939fb72018-11-13 13:34:41 -08009635 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9636 if (in_ctxt != NULL) {
9637 list_remove(&in_ctxt->list);
9638 free(in_ctxt);
9639 } else {
9640 ALOGW("%s, input stream already closed", __func__);
9641 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009642 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309643 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009644 return;
9645}
9646
Aalique Grahame22e49102018-12-18 14:23:57 -08009647/* verifies input and output devices and their capabilities.
9648 *
9649 * This verification is required when enabling extended bit-depth or
9650 * sampling rates, as not all qcom products support it.
9651 *
9652 * Suitable for calling only on initialization such as adev_open().
9653 * It fills the audio_device use_case_table[] array.
9654 *
9655 * Has a side-effect that it needs to configure audio routing / devices
9656 * in order to power up the devices and read the device parameters.
9657 * It does not acquire any hw device lock. Should restore the devices
9658 * back to "normal state" upon completion.
9659 */
9660static int adev_verify_devices(struct audio_device *adev)
9661{
9662 /* enumeration is a bit difficult because one really wants to pull
9663 * the use_case, device id, etc from the hidden pcm_device_table[].
9664 * In this case there are the following use cases and device ids.
9665 *
9666 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9667 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9668 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9669 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9670 * [USECASE_AUDIO_RECORD] = {0, 0},
9671 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9672 * [USECASE_VOICE_CALL] = {2, 2},
9673 *
9674 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9675 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9676 */
9677
9678 /* should be the usecases enabled in adev_open_input_stream() */
9679 static const int test_in_usecases[] = {
9680 USECASE_AUDIO_RECORD,
9681 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9682 };
9683 /* should be the usecases enabled in adev_open_output_stream()*/
9684 static const int test_out_usecases[] = {
9685 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9686 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9687 };
9688 static const usecase_type_t usecase_type_by_dir[] = {
9689 PCM_PLAYBACK,
9690 PCM_CAPTURE,
9691 };
9692 static const unsigned flags_by_dir[] = {
9693 PCM_OUT,
9694 PCM_IN,
9695 };
9696
9697 size_t i;
9698 unsigned dir;
9699 const unsigned card_id = adev->snd_card;
9700
9701 for (dir = 0; dir < 2; ++dir) {
9702 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9703 const unsigned flags_dir = flags_by_dir[dir];
9704 const size_t testsize =
9705 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9706 const int *testcases =
9707 dir ? test_in_usecases : test_out_usecases;
9708 const audio_devices_t audio_device =
9709 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9710
9711 for (i = 0; i < testsize; ++i) {
9712 const audio_usecase_t audio_usecase = testcases[i];
9713 int device_id;
9714 struct pcm_params **pparams;
9715 struct stream_out out;
9716 struct stream_in in;
9717 struct audio_usecase uc_info;
9718 int retval;
9719
9720 pparams = &adev->use_case_table[audio_usecase];
9721 pcm_params_free(*pparams); /* can accept null input */
9722 *pparams = NULL;
9723
9724 /* find the device ID for the use case (signed, for error) */
9725 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9726 if (device_id < 0)
9727 continue;
9728
9729 /* prepare structures for device probing */
9730 memset(&uc_info, 0, sizeof(uc_info));
9731 uc_info.id = audio_usecase;
9732 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009733 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009734 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009735 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009736 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009737 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009738 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9739 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009740 }
9741 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009742 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009743 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009744 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009745 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009746 uc_info.in_snd_device = SND_DEVICE_NONE;
9747 uc_info.out_snd_device = SND_DEVICE_NONE;
9748 list_add_tail(&adev->usecase_list, &uc_info.list);
9749
9750 /* select device - similar to start_(in/out)put_stream() */
9751 retval = select_devices(adev, audio_usecase);
9752 if (retval >= 0) {
9753 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9754#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009755 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009756 if (*pparams) {
9757 ALOGV("%s: (%s) card %d device %d", __func__,
9758 dir ? "input" : "output", card_id, device_id);
9759 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9760 } else {
9761 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9762 }
9763#endif
9764 }
9765
9766 /* deselect device - similar to stop_(in/out)put_stream() */
9767 /* 1. Get and set stream specific mixer controls */
9768 retval = disable_audio_route(adev, &uc_info);
9769 /* 2. Disable the rx device */
9770 retval = disable_snd_device(adev,
9771 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9772 list_remove(&uc_info.list);
9773 }
9774 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009775 return 0;
9776}
9777
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009778int update_patch(unsigned int num_sources,
9779 const struct audio_port_config *sources,
9780 unsigned int num_sinks,
9781 const struct audio_port_config *sinks,
9782 audio_patch_handle_t handle,
9783 struct audio_patch_info *p_info,
9784 patch_type_t patch_type, bool new_patch)
9785{
9786 ALOGD("%s: enter", __func__);
9787
9788 if (p_info == NULL) {
9789 ALOGE("%s: Invalid patch pointer", __func__);
9790 return -EINVAL;
9791 }
9792
9793 if (new_patch) {
9794 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9795 if (p_info->patch == NULL) {
9796 ALOGE("%s: Could not allocate patch", __func__);
9797 return -ENOMEM;
9798 }
9799 }
9800
9801 p_info->patch->id = handle;
9802 p_info->patch->num_sources = num_sources;
9803 p_info->patch->num_sinks = num_sinks;
9804
9805 for (int i = 0; i < num_sources; i++)
9806 p_info->patch->sources[i] = sources[i];
9807 for (int i = 0; i < num_sinks; i++)
9808 p_info->patch->sinks[i] = sinks[i];
9809
9810 p_info->patch_type = patch_type;
9811 return 0;
9812}
9813
9814audio_patch_handle_t generate_patch_handle()
9815{
9816 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9817 if (++patch_handle < 0)
9818 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9819 return patch_handle;
9820}
9821
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309822int adev_create_audio_patch(struct audio_hw_device *dev,
9823 unsigned int num_sources,
9824 const struct audio_port_config *sources,
9825 unsigned int num_sinks,
9826 const struct audio_port_config *sinks,
9827 audio_patch_handle_t *handle)
9828{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009829 int ret = 0;
9830 struct audio_device *adev = (struct audio_device *)dev;
9831 struct audio_patch_info *p_info = NULL;
9832 patch_type_t patch_type = PATCH_NONE;
9833 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9834 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9835 struct audio_stream_info *s_info = NULL;
9836 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009837 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009838 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9839 bool new_patch = false;
9840 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309841
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009842 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9843 num_sources, num_sinks, *handle);
9844
9845 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9846 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9847 ALOGE("%s: Invalid patch arguments", __func__);
9848 ret = -EINVAL;
9849 goto done;
9850 }
9851
9852 if (num_sources > 1) {
9853 ALOGE("%s: Multiple sources are not supported", __func__);
9854 ret = -EINVAL;
9855 goto done;
9856 }
9857
9858 if (sources == NULL || sinks == NULL) {
9859 ALOGE("%s: Invalid sources or sinks port config", __func__);
9860 ret = -EINVAL;
9861 goto done;
9862 }
9863
9864 ALOGV("%s: source role %d, source type %d", __func__,
9865 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009866 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009867
9868 // Populate source/sink information and fetch stream info
9869 switch (sources[0].type) {
9870 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9871 device_type = sources[0].ext.device.type;
9872 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009873 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009874 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9875 patch_type = PATCH_CAPTURE;
9876 io_handle = sinks[0].ext.mix.handle;
9877 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009878 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009879 __func__, device_type, io_handle);
9880 } else {
9881 // Device to device patch is not implemented.
9882 // This space will need changes if audio HAL
9883 // handles device to device patches in the future.
9884 patch_type = PATCH_DEVICE_LOOPBACK;
9885 }
9886 break;
9887 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9888 io_handle = sources[0].ext.mix.handle;
9889 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009890 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009891 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009892 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009893 }
9894 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009895 ALOGD("%s: Playback patch from mix handle %d to device %x",
9896 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009897 break;
9898 case AUDIO_PORT_TYPE_SESSION:
9899 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009900 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9901 ret = -EINVAL;
9902 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009903 }
9904
9905 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009906
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009907 // Generate patch info and update patch
9908 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009909 *handle = generate_patch_handle();
9910 p_info = (struct audio_patch_info *)
9911 calloc(1, sizeof(struct audio_patch_info));
9912 if (p_info == NULL) {
9913 ALOGE("%s: Failed to allocate memory", __func__);
9914 pthread_mutex_unlock(&adev->lock);
9915 ret = -ENOMEM;
9916 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009917 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009918 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009919 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009920 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009921 if (p_info == NULL) {
9922 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9923 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009924 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009925 ret = -EINVAL;
9926 goto done;
9927 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009928 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009929 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009930 *handle, p_info, patch_type, new_patch);
9931
9932 // Fetch stream info of associated mix for playback or capture patches
9933 if (p_info->patch_type == PATCH_PLAYBACK ||
9934 p_info->patch_type == PATCH_CAPTURE) {
9935 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9936 if (s_info == NULL) {
9937 ALOGE("%s: Failed to obtain stream info", __func__);
9938 if (new_patch)
9939 free(p_info);
9940 pthread_mutex_unlock(&adev->lock);
9941 ret = -EINVAL;
9942 goto done;
9943 }
9944 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9945 s_info->patch_handle = *handle;
9946 stream = s_info->stream;
9947 }
9948 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009949
9950 // Update routing for stream
9951 if (stream != NULL) {
9952 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009953 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009954 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009955 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009956 if (ret < 0) {
9957 pthread_mutex_lock(&adev->lock);
9958 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9959 if (new_patch)
9960 free(p_info);
9961 pthread_mutex_unlock(&adev->lock);
9962 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9963 goto done;
9964 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009965 }
9966
9967 // Add new patch to patch map
9968 if (!ret && new_patch) {
9969 pthread_mutex_lock(&adev->lock);
9970 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009971 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009972 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009973 }
9974
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009975done:
9976 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009977 num_sources,
9978 sources,
9979 num_sinks,
9980 sinks,
9981 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009982 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009983 num_sources,
9984 sources,
9985 num_sinks,
9986 sinks,
9987 handle);
9988 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309989}
9990
9991int adev_release_audio_patch(struct audio_hw_device *dev,
9992 audio_patch_handle_t handle)
9993{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009994 struct audio_device *adev = (struct audio_device *) dev;
9995 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009996 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009997 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -08009998
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009999 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10000 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10001 ret = -EINVAL;
10002 goto done;
10003 }
10004
10005 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010006 pthread_mutex_lock(&adev->lock);
10007 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010008 if (p_info == NULL) {
10009 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010010 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010011 ret = -EINVAL;
10012 goto done;
10013 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010014 struct audio_patch *patch = p_info->patch;
10015 if (patch == NULL) {
10016 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010017 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010018 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010019 goto done;
10020 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010021 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10022 switch (patch->sources[0].type) {
10023 case AUDIO_PORT_TYPE_MIX:
10024 io_handle = patch->sources[0].ext.mix.handle;
10025 break;
10026 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010027 if (p_info->patch_type == PATCH_CAPTURE)
10028 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010029 break;
10030 case AUDIO_PORT_TYPE_SESSION:
10031 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010032 pthread_mutex_unlock(&adev->lock);
10033 ret = -EINVAL;
10034 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010035 }
10036
10037 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010038 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010039 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010040 if (patch_type == PATCH_PLAYBACK ||
10041 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010042 struct audio_stream_info *s_info =
10043 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10044 if (s_info == NULL) {
10045 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10046 pthread_mutex_unlock(&adev->lock);
10047 goto done;
10048 }
10049 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10050 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010051 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010052 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010053
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010054 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010055 struct listnode devices;
10056 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010057 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010058 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010059 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010060 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010061 }
10062
10063 if (ret < 0)
10064 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10065
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010066done:
10067 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10068 audio_extn_auto_hal_release_audio_patch(dev, handle);
10069
10070 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010071 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010072}
10073
10074int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10075{
Derek Chenf13dd492018-11-13 14:53:51 -080010076 int ret = 0;
10077
10078 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10079 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10080 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010081}
10082
10083int adev_set_audio_port_config(struct audio_hw_device *dev,
10084 const struct audio_port_config *config)
10085{
Derek Chenf13dd492018-11-13 14:53:51 -080010086 int ret = 0;
10087
10088 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10089 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10090 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010091}
10092
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010093static int adev_dump(const audio_hw_device_t *device __unused,
10094 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010095{
10096 return 0;
10097}
10098
10099static int adev_close(hw_device_t *device)
10100{
Aalique Grahame22e49102018-12-18 14:23:57 -080010101 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010102 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010103
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010104 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010105 return 0;
10106
10107 pthread_mutex_lock(&adev_init_lock);
10108
10109 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010110 if (audio_extn_spkr_prot_is_enabled())
10111 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010112 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010113 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010114 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010115 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010116 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010117 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010118 audio_extn_utils_release_streams_cfg_lists(
10119 &adev->streams_output_cfg_list,
10120 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010121 if (audio_extn_qap_is_enabled())
10122 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010123 if (audio_extn_qaf_is_enabled())
10124 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010125 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010126 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010127 free(adev->snd_dev_ref_cnt);
10128 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010129 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10130 pcm_params_free(adev->use_case_table[i]);
10131 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010132 if (adev->adm_deinit)
10133 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010134 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010135 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010136 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010137 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010138 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010139 if (adev->device_cfg_params) {
10140 free(adev->device_cfg_params);
10141 adev->device_cfg_params = NULL;
10142 }
Derek Chend2530072014-11-24 12:39:14 -080010143 if(adev->ext_hw_plugin)
10144 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010145 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010146 free_map(adev->patch_map);
10147 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010148 free(device);
10149 adev = NULL;
10150 }
10151 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010152 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010153 return 0;
10154}
10155
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010156/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10157 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10158 * just that it _might_ work.
10159 */
10160static int period_size_is_plausible_for_low_latency(int period_size)
10161{
10162 switch (period_size) {
10163 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010164 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010165 case 240:
10166 case 320:
10167 case 480:
10168 return 1;
10169 default:
10170 return 0;
10171 }
10172}
10173
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010174static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10175{
10176 bool is_snd_card_status = false;
10177 bool is_ext_device_status = false;
10178 char value[32];
10179 int card = -1;
10180 card_status_t status;
10181
10182 if (cookie != adev || !parms)
10183 return;
10184
10185 if (!parse_snd_card_status(parms, &card, &status)) {
10186 is_snd_card_status = true;
10187 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10188 is_ext_device_status = true;
10189 } else {
10190 // not a valid event
10191 return;
10192 }
10193
10194 pthread_mutex_lock(&adev->lock);
10195 if (card == adev->snd_card || is_ext_device_status) {
10196 if (is_snd_card_status && adev->card_status != status) {
10197 adev->card_status = status;
10198 platform_snd_card_update(adev->platform, status);
10199 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010200 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010201 if (status == CARD_STATUS_OFFLINE)
10202 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010203 } else if (is_ext_device_status) {
10204 platform_set_parameters(adev->platform, parms);
10205 }
10206 }
10207 pthread_mutex_unlock(&adev->lock);
10208 return;
10209}
10210
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010211/* out and adev lock held */
10212static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10213{
10214 struct audio_usecase *uc_info;
10215 float left_p;
10216 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010217 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010218
10219 uc_info = get_usecase_from_list(adev, out->usecase);
10220 if (uc_info == NULL) {
10221 ALOGE("%s: Could not find the usecase (%d) in the list",
10222 __func__, out->usecase);
10223 return -EINVAL;
10224 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010225 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010226
10227 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10228 out->usecase, use_case_table[out->usecase]);
10229
10230 if (restore) {
10231 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010232 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010233 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010234 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10235 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010236 pthread_mutex_lock(&out->compr_mute_lock);
10237 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010238 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010239 out->a2dp_compress_mute = false;
10240 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10241 }
10242 pthread_mutex_unlock(&out->compr_mute_lock);
10243 }
10244 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010245 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10246 // mute compress stream if suspended
10247 pthread_mutex_lock(&out->compr_mute_lock);
10248 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010249 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010250 assign_devices(&devices, &out->device_list);
10251 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010252 left_p = out->volume_l;
10253 right_p = out->volume_r;
10254 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10255 compress_pause(out->compr);
10256 out_set_compr_volume(&out->stream, (float)0, (float)0);
10257 out->a2dp_compress_mute = true;
10258 select_devices(adev, out->usecase);
10259 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10260 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010261 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010262 out->volume_l = left_p;
10263 out->volume_r = right_p;
10264 }
Zhou Songc576a452019-09-09 14:17:40 +080010265 pthread_mutex_unlock(&out->compr_mute_lock);
10266 } else {
10267 // tear down a2dp path for non offloaded streams
10268 if (audio_extn_a2dp_source_is_suspended())
10269 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010270 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010271 }
10272 ALOGV("%s: exit", __func__);
10273 return 0;
10274}
10275
10276int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10277{
10278 int ret = 0;
10279
10280 lock_output_stream(out);
10281 pthread_mutex_lock(&adev->lock);
10282
10283 ret = check_a2dp_restore_l(adev, out, restore);
10284
10285 pthread_mutex_unlock(&adev->lock);
10286 pthread_mutex_unlock(&out->lock);
10287 return ret;
10288}
10289
Haynes Mathew George01156f92018-04-13 15:29:54 -070010290void adev_on_battery_status_changed(bool charging)
10291{
10292 pthread_mutex_lock(&adev->lock);
10293 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10294 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010295 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010296 pthread_mutex_unlock(&adev->lock);
10297}
10298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010299static int adev_open(const hw_module_t *module, const char *name,
10300 hw_device_t **device)
10301{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010302 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010303 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010304 char mixer_ctl_name[128] = {0};
10305 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010306
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010307 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010308 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10309
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010310 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010311 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010312 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010313 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010314 ALOGD("%s: returning existing instance of adev", __func__);
10315 ALOGD("%s: exit", __func__);
10316 pthread_mutex_unlock(&adev_init_lock);
10317 return 0;
10318 }
10319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010320 adev = calloc(1, sizeof(struct audio_device));
10321
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010322 if (!adev) {
10323 pthread_mutex_unlock(&adev_init_lock);
10324 return -ENOMEM;
10325 }
10326
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010327 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10328
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010329 // register audio ext hidl at the earliest
10330 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010331#ifdef DYNAMIC_LOG_ENABLED
10332 register_for_dynamic_logging("hal");
10333#endif
10334
Derek Chenf939fb72018-11-13 13:34:41 -080010335 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010336 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010337 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10338 maj_version = atoi(value);
10339
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010340 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010341 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010342 adev->device.common.module = (struct hw_module_t *)module;
10343 adev->device.common.close = adev_close;
10344
10345 adev->device.init_check = adev_init_check;
10346 adev->device.set_voice_volume = adev_set_voice_volume;
10347 adev->device.set_master_volume = adev_set_master_volume;
10348 adev->device.get_master_volume = adev_get_master_volume;
10349 adev->device.set_master_mute = adev_set_master_mute;
10350 adev->device.get_master_mute = adev_get_master_mute;
10351 adev->device.set_mode = adev_set_mode;
10352 adev->device.set_mic_mute = adev_set_mic_mute;
10353 adev->device.get_mic_mute = adev_get_mic_mute;
10354 adev->device.set_parameters = adev_set_parameters;
10355 adev->device.get_parameters = adev_get_parameters;
10356 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10357 adev->device.open_output_stream = adev_open_output_stream;
10358 adev->device.close_output_stream = adev_close_output_stream;
10359 adev->device.open_input_stream = adev_open_input_stream;
10360 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010361 adev->device.create_audio_patch = adev_create_audio_patch;
10362 adev->device.release_audio_patch = adev_release_audio_patch;
10363 adev->device.get_audio_port = adev_get_audio_port;
10364 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010365 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010366 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010367
10368 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010369 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010370 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010371 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010372 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010373 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010374 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010375 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010376 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010377 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010378 /* Init audio and voice feature */
10379 audio_extn_feature_init();
10380 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010381 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010382 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010383 list_init(&adev->active_inputs_list);
10384 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010385 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010386 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10387 audio_extn_utils_hash_eq);
10388 if (!adev->io_streams_map) {
10389 ALOGE("%s: Could not create io streams map", __func__);
10390 ret = -ENOMEM;
10391 goto adev_open_err;
10392 }
10393 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10394 audio_extn_utils_hash_eq);
10395 if (!adev->patch_map) {
10396 ALOGE("%s: Could not create audio patch map", __func__);
10397 ret = -ENOMEM;
10398 goto adev_open_err;
10399 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010400 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010401 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010402 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010403 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010404 adev->perf_lock_opts[0] = 0x101;
10405 adev->perf_lock_opts[1] = 0x20E;
10406 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010407 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010408 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010409 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010410 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010411
Zhou Song68ebc352019-12-05 17:11:15 +080010412 audio_extn_perf_lock_init();
10413
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010414 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010415 adev->platform = platform_init(adev);
10416 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010417 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010418 ret = -EINVAL;
10419 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010420 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010421
Aalique Grahame22e49102018-12-18 14:23:57 -080010422 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010423 if (audio_extn_qap_is_enabled()) {
10424 ret = audio_extn_qap_init(adev);
10425 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010426 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010427 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010428 }
10429 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10430 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10431 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010432
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010433 if (audio_extn_qaf_is_enabled()) {
10434 ret = audio_extn_qaf_init(adev);
10435 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010436 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010437 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010438 }
10439
10440 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10441 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10442 }
10443
Derek Chenae7b0342019-02-08 15:17:04 -080010444 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010445 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10446
Eric Laurentc4aef752013-09-12 17:45:53 -070010447 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10448 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10449 if (adev->visualizer_lib == NULL) {
10450 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10451 } else {
10452 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10453 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010454 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010455 "visualizer_hal_start_output");
10456 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010457 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010458 "visualizer_hal_stop_output");
10459 }
10460 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010461 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010462 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010463 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010464 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010465 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010466 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010467
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010468 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10469 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10470 if (adev->offload_effects_lib == NULL) {
10471 ALOGE("%s: DLOPEN failed for %s", __func__,
10472 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10473 } else {
10474 ALOGV("%s: DLOPEN successful for %s", __func__,
10475 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10476 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010477 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010478 "offload_effects_bundle_hal_start_output");
10479 adev->offload_effects_stop_output =
10480 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10481 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010482 adev->offload_effects_set_hpx_state =
10483 (int (*)(bool))dlsym(adev->offload_effects_lib,
10484 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010485 adev->offload_effects_get_parameters =
10486 (void (*)(struct str_parms *, struct str_parms *))
10487 dlsym(adev->offload_effects_lib,
10488 "offload_effects_bundle_get_parameters");
10489 adev->offload_effects_set_parameters =
10490 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10491 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010492 }
10493 }
10494
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010495 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10496 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10497 if (adev->adm_lib == NULL) {
10498 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10499 } else {
10500 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10501 adev->adm_init = (adm_init_t)
10502 dlsym(adev->adm_lib, "adm_init");
10503 adev->adm_deinit = (adm_deinit_t)
10504 dlsym(adev->adm_lib, "adm_deinit");
10505 adev->adm_register_input_stream = (adm_register_input_stream_t)
10506 dlsym(adev->adm_lib, "adm_register_input_stream");
10507 adev->adm_register_output_stream = (adm_register_output_stream_t)
10508 dlsym(adev->adm_lib, "adm_register_output_stream");
10509 adev->adm_deregister_stream = (adm_deregister_stream_t)
10510 dlsym(adev->adm_lib, "adm_deregister_stream");
10511 adev->adm_request_focus = (adm_request_focus_t)
10512 dlsym(adev->adm_lib, "adm_request_focus");
10513 adev->adm_abandon_focus = (adm_abandon_focus_t)
10514 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010515 adev->adm_set_config = (adm_set_config_t)
10516 dlsym(adev->adm_lib, "adm_set_config");
10517 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10518 dlsym(adev->adm_lib, "adm_request_focus_v2");
10519 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10520 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10521 adev->adm_on_routing_change = (adm_on_routing_change_t)
10522 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010523 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10524 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010525 }
10526 }
10527
Aalique Grahame22e49102018-12-18 14:23:57 -080010528 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010529 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010530 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010531 //initialize this to false for now,
10532 //this will be set to true through set param
10533 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010534
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010535 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010536 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010537
10538 if (k_enable_extended_precision)
10539 adev_verify_devices(adev);
10540
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010541 adev->dsp_bit_width_enforce_mode =
10542 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010543
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010544 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10545 &adev->streams_output_cfg_list,
10546 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010547
Kiran Kandi910e1862013-10-29 13:29:42 -070010548 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010549
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010550 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010551 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010552 trial = atoi(value);
10553 if (period_size_is_plausible_for_low_latency(trial)) {
10554 pcm_config_low_latency.period_size = trial;
10555 pcm_config_low_latency.start_threshold = trial / 4;
10556 pcm_config_low_latency.avail_min = trial / 4;
10557 configured_low_latency_capture_period_size = trial;
10558 }
10559 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010560 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10561 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010562 trial = atoi(value);
10563 if (period_size_is_plausible_for_low_latency(trial)) {
10564 configured_low_latency_capture_period_size = trial;
10565 }
10566 }
10567
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010568 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10569
Eric Laurent4b084132018-10-19 17:33:43 -070010570 adev->camera_orientation = CAMERA_DEFAULT;
10571
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010572 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010573 af_period_multiplier = atoi(value);
10574 if (af_period_multiplier < 0)
10575 af_period_multiplier = 2;
10576 else if (af_period_multiplier > 4)
10577 af_period_multiplier = 4;
10578
10579 ALOGV("new period_multiplier = %d", af_period_multiplier);
10580 }
10581
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010582 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010583
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010584 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010585 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010586 pthread_mutex_unlock(&adev_init_lock);
10587
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010588 if (adev->adm_init)
10589 adev->adm_data = adev->adm_init();
10590
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010591 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010592 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010593
10594 audio_extn_snd_mon_init();
10595 pthread_mutex_lock(&adev->lock);
10596 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10597 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010598 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10599 /*
10600 * if the battery state callback happens before charging can be queried,
10601 * it will be guarded with the adev->lock held in the cb function and so
10602 * the callback value will reflect the latest state
10603 */
10604 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010605 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010606 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010607 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010608 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010609 /* Allocate memory for Device config params */
10610 adev->device_cfg_params = (struct audio_device_config_param*)
10611 calloc(platform_get_max_codec_backend(),
10612 sizeof(struct audio_device_config_param));
10613 if (adev->device_cfg_params == NULL)
10614 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010615
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010616 /*
10617 * Check if new PSPD matrix mixer control is supported. If not
10618 * supported, then set flag so that old mixer ctrl is sent while
10619 * sending pspd coefficients on older kernel version. Query mixer
10620 * control for default pcm id and channel value one.
10621 */
10622 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10623 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10624
10625 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10626 if (!ctl) {
10627 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10628 __func__, mixer_ctl_name);
10629 adev->use_old_pspd_mix_ctrl = true;
10630 }
10631
Eric Laurent994a6932013-07-17 11:51:42 -070010632 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010633 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010634
10635adev_open_err:
10636 free_map(adev->patch_map);
10637 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010638 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010639 pthread_mutex_destroy(&adev->lock);
10640 free(adev);
10641 adev = NULL;
10642 *device = NULL;
10643 pthread_mutex_unlock(&adev_init_lock);
10644 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010645}
10646
10647static struct hw_module_methods_t hal_module_methods = {
10648 .open = adev_open,
10649};
10650
10651struct audio_module HAL_MODULE_INFO_SYM = {
10652 .common = {
10653 .tag = HARDWARE_MODULE_TAG,
10654 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10655 .hal_api_version = HARDWARE_HAL_API_VERSION,
10656 .id = AUDIO_HARDWARE_MODULE_ID,
10657 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010658 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010659 .methods = &hal_module_methods,
10660 },
10661};