blob: e7c8a93d77123aedf15e34c1609187a4e02c3508 [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",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700331 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
332 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700333 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700334 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700335 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
341 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700343 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
344 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700345 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800346 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700347
Eric Laurentb23d5282013-05-14 15:27:20 -0700348 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700349 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530350 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
351 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
352 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530353 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
354 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700355 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700356 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700357 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700358 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700359
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800360 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800361 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400362 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
363 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700364
Derek Chenf7092792017-05-23 12:23:53 -0400365 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700366 [USECASE_VOICE2_CALL] = "voice2-call",
367 [USECASE_VOLTE_CALL] = "volte-call",
368 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800369 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800370 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
371 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800372 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700373 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
374 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
375 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800376 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
377 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
378 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
379
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700380 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
381 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700382 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
383 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700384
385 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
386 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800387 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530388 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700389
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530390 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530391 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
392 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700393
394 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
395 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530396 /* For Interactive Audio Streams */
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
401 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
402 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
403 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700405
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800406 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
407
Derek Chenf6318be2017-06-12 17:16:24 -0400408 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
409
410 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
411 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
412 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
413 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800414 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700415 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530416 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700417};
418
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700419static const audio_usecase_t offload_usecases[] = {
420 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700421 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
422 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
426 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
427 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
428 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700429};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800430
Varun Balaraje49253e2017-07-06 19:48:56 +0530431static const audio_usecase_t interactive_usecases[] = {
432 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
437 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
438 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
440};
441
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800442#define STRING_TO_ENUM(string) { #string, string }
443
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800444struct string_to_enum {
445 const char *name;
446 uint32_t value;
447};
448
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700449static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800455 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
456 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700458 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
459 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
460 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
461 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
466 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
467 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800469};
470
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700471static const struct string_to_enum formats_name_to_enum_table[] = {
472 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
473 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
474 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700475 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
476 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
477 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700478 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800479 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
480 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700481 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800482};
483
484//list of all supported sample rates by HDMI specification.
485static const int out_hdmi_sample_rates[] = {
486 32000, 44100, 48000, 88200, 96000, 176400, 192000,
487};
488
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700489static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800490 STRING_TO_ENUM(32000),
491 STRING_TO_ENUM(44100),
492 STRING_TO_ENUM(48000),
493 STRING_TO_ENUM(88200),
494 STRING_TO_ENUM(96000),
495 STRING_TO_ENUM(176400),
496 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800497 STRING_TO_ENUM(352800),
498 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700499};
500
Carter Hsu2e429db2019-05-14 18:50:52 +0800501struct in_effect_list {
502 struct listnode list;
503 effect_handle_t handle;
504};
505
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700506static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700507static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700508static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700509//cache last MBDRC cal step level
510static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700511
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530512static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
513static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700514static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800515static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530516static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530517
Derek Chen6f293672019-04-01 01:40:24 -0700518static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
519static void in_snd_mon_cb(void * stream, struct str_parms * parms);
520static void out_snd_mon_cb(void * stream, struct str_parms * parms);
521
Zhou Song331c8e52019-08-26 14:16:12 +0800522static int configure_btsco_sample_rate(snd_device_t snd_device);
523
Vatsal Buchac09ae062018-11-14 13:25:08 +0530524#ifdef AUDIO_FEATURE_ENABLED_GCOV
525extern void __gcov_flush();
526static void enable_gcov()
527{
528 __gcov_flush();
529}
530#else
531static void enable_gcov()
532{
533}
534#endif
535
justinweng20fb6d82019-02-21 18:49:00 -0700536static int in_set_microphone_direction(const struct audio_stream_in *stream,
537 audio_microphone_direction_t dir);
538static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
539
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700540static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
541 int flags __unused)
542{
543 int dir = 0;
544 switch (uc_id) {
545 case USECASE_AUDIO_RECORD_LOW_LATENCY:
546 dir = 1;
547 case USECASE_AUDIO_PLAYBACK_ULL:
548 break;
549 default:
550 return false;
551 }
552
553 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
554 PCM_PLAYBACK : PCM_CAPTURE);
555 if (adev->adm_is_noirq_avail)
556 return adev->adm_is_noirq_avail(adev->adm_data,
557 adev->snd_card, dev_id, dir);
558 return false;
559}
560
561static void register_out_stream(struct stream_out *out)
562{
563 struct audio_device *adev = out->dev;
564 if (is_offload_usecase(out->usecase) ||
565 !adev->adm_register_output_stream)
566 return;
567
568 // register stream first for backward compatibility
569 adev->adm_register_output_stream(adev->adm_data,
570 out->handle,
571 out->flags);
572
573 if (!adev->adm_set_config)
574 return;
575
576 if (out->realtime)
577 adev->adm_set_config(adev->adm_data,
578 out->handle,
579 out->pcm, &out->config);
580}
581
582static void register_in_stream(struct stream_in *in)
583{
584 struct audio_device *adev = in->dev;
585 if (!adev->adm_register_input_stream)
586 return;
587
588 adev->adm_register_input_stream(adev->adm_data,
589 in->capture_handle,
590 in->flags);
591
592 if (!adev->adm_set_config)
593 return;
594
595 if (in->realtime)
596 adev->adm_set_config(adev->adm_data,
597 in->capture_handle,
598 in->pcm,
599 &in->config);
600}
601
602static void request_out_focus(struct stream_out *out, long ns)
603{
604 struct audio_device *adev = out->dev;
605
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700606 if (adev->adm_request_focus_v2)
607 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
608 else if (adev->adm_request_focus)
609 adev->adm_request_focus(adev->adm_data, out->handle);
610}
611
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700612static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700613{
614 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700615 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700616
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700617 if (adev->adm_request_focus_v2_1)
618 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
619 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700620 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
621 else if (adev->adm_request_focus)
622 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700623
624 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700625}
626
627static void release_out_focus(struct stream_out *out)
628{
629 struct audio_device *adev = out->dev;
630
631 if (adev->adm_abandon_focus)
632 adev->adm_abandon_focus(adev->adm_data, out->handle);
633}
634
635static void release_in_focus(struct stream_in *in)
636{
637 struct audio_device *adev = in->dev;
638 if (adev->adm_abandon_focus)
639 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
640}
641
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530642static int parse_snd_card_status(struct str_parms *parms, int *card,
643 card_status_t *status)
644{
645 char value[32]={0};
646 char state[32]={0};
647
648 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
649 if (ret < 0)
650 return -1;
651
652 // sscanf should be okay as value is of max length 32.
653 // same as sizeof state.
654 if (sscanf(value, "%d,%s", card, state) < 2)
655 return -1;
656
657 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
658 CARD_STATUS_OFFLINE;
659 return 0;
660}
661
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700662static inline void adjust_frames_for_device_delay(struct stream_out *out,
663 uint32_t *dsp_frames) {
664 // Adjustment accounts for A2dp encoder latency with offload usecases
665 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800666 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700667 unsigned long offset =
668 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
669 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
670 }
671}
672
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700673static inline bool free_entry(void *key __unused,
674 void *value, void *context __unused)
675{
676 free(value);
677 return true;
678}
679
680static inline void free_map(Hashmap *map)
681{
682 if (map) {
683 hashmapForEach(map, free_entry, (void *) NULL);
684 hashmapFree(map);
685 }
686}
687
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800688static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700689 audio_patch_handle_t patch_handle)
690{
691 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
692 return;
693
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700694 struct audio_patch_info *p_info =
695 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
696 if (p_info) {
697 ALOGV("%s: Remove patch %d", __func__, patch_handle);
698 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
699 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700700 free(p_info);
701 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700702}
703
704static inline int io_streams_map_insert(struct audio_device *adev,
705 struct audio_stream *stream,
706 audio_io_handle_t handle,
707 audio_patch_handle_t patch_handle)
708{
709 struct audio_stream_info *s_info =
710 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
711
712 if (s_info == NULL) {
713 ALOGE("%s: Could not allocate stream info", __func__);
714 return -ENOMEM;
715 }
716 s_info->stream = stream;
717 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700718
719 pthread_mutex_lock(&adev->lock);
720 struct audio_stream_info *stream_info =
721 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700722 if (stream_info != NULL)
723 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800724 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700725 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
726 return 0;
727}
728
729static inline void io_streams_map_remove(struct audio_device *adev,
730 audio_io_handle_t handle)
731{
732 pthread_mutex_lock(&adev->lock);
733 struct audio_stream_info *s_info =
734 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700735 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800736 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700737 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800738 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700739 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800740done:
741 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700742 return;
743}
744
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800745static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700746 audio_patch_handle_t handle)
747{
748 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700749 p_info = (struct audio_patch_info *)
750 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700751 return p_info;
752}
753
vivek mehtaa76401a2015-04-24 14:12:15 -0700754__attribute__ ((visibility ("default")))
755bool audio_hw_send_gain_dep_calibration(int level) {
756 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700757 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700758
759 pthread_mutex_lock(&adev_init_lock);
760
761 if (adev != NULL && adev->platform != NULL) {
762 pthread_mutex_lock(&adev->lock);
763 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700764
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530765 // cache level info for any of the use case which
766 // was not started.
767 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700768
vivek mehtaa76401a2015-04-24 14:12:15 -0700769 pthread_mutex_unlock(&adev->lock);
770 } else {
771 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
772 }
773
774 pthread_mutex_unlock(&adev_init_lock);
775
776 return ret_val;
777}
778
Ashish Jain5106d362016-05-11 19:23:33 +0530779static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
780{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800781 bool gapless_enabled = false;
782 const char *mixer_ctl_name = "Compress Gapless Playback";
783 struct mixer_ctl *ctl;
784
785 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700786 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530787
788 /*Disable gapless if its AV playback*/
789 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800790
791 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
792 if (!ctl) {
793 ALOGE("%s: Could not get ctl for mixer cmd - %s",
794 __func__, mixer_ctl_name);
795 return -EINVAL;
796 }
797
798 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
799 ALOGE("%s: Could not set gapless mode %d",
800 __func__, gapless_enabled);
801 return -EINVAL;
802 }
803 return 0;
804}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700805
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700806__attribute__ ((visibility ("default")))
807int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
808 int table_size) {
809 int ret_val = 0;
810 ALOGV("%s: enter ... ", __func__);
811
812 pthread_mutex_lock(&adev_init_lock);
813 if (adev == NULL) {
814 ALOGW("%s: adev is NULL .... ", __func__);
815 goto done;
816 }
817
818 pthread_mutex_lock(&adev->lock);
819 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
820 pthread_mutex_unlock(&adev->lock);
821done:
822 pthread_mutex_unlock(&adev_init_lock);
823 ALOGV("%s: exit ... ", __func__);
824 return ret_val;
825}
826
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800827bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800828{
829 bool ret = false;
830 ALOGV("%s: enter ...", __func__);
831
832 pthread_mutex_lock(&adev_init_lock);
833
834 if (adev != NULL && adev->platform != NULL) {
835 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800836 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800837 pthread_mutex_unlock(&adev->lock);
838 }
839
840 pthread_mutex_unlock(&adev_init_lock);
841
842 ALOGV("%s: exit with ret %d", __func__, ret);
843 return ret;
844}
Aalique Grahame22e49102018-12-18 14:23:57 -0800845
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700846static bool is_supported_format(audio_format_t format)
847{
Eric Laurent86e17132013-09-12 17:49:30 -0700848 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530849 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530850 format == AUDIO_FORMAT_AAC_LC ||
851 format == AUDIO_FORMAT_AAC_HE_V1 ||
852 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530853 format == AUDIO_FORMAT_AAC_ADTS_LC ||
854 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
855 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530856 format == AUDIO_FORMAT_AAC_LATM_LC ||
857 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
858 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530859 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
860 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530861 format == AUDIO_FORMAT_PCM_FLOAT ||
862 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700863 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530864 format == AUDIO_FORMAT_AC3 ||
865 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700866 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530867 format == AUDIO_FORMAT_DTS ||
868 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800869 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530870 format == AUDIO_FORMAT_ALAC ||
871 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530872 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530873 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800874 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530875 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700876 format == AUDIO_FORMAT_APTX ||
877 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800878 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700879
880 return false;
881}
882
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700883static inline bool is_mmap_usecase(audio_usecase_t uc_id)
884{
885 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800886 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700887 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
888}
889
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700890static inline bool is_valid_volume(float left, float right)
891{
892 return ((left >= 0.0f && right >= 0.0f) ? true : false);
893}
894
Avinash Vaish71a8b972014-07-24 15:36:33 +0530895static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
896 struct audio_usecase *uc_info)
897{
898 struct listnode *node;
899 struct audio_usecase *usecase;
900
901 if (uc_info == NULL)
902 return -EINVAL;
903
904 /* Re-route all voice usecases on the shared backend other than the
905 specified usecase to new snd devices */
906 list_for_each(node, &adev->usecase_list) {
907 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800908 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530909 enable_audio_route(adev, usecase);
910 }
911 return 0;
912}
913
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530914static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530915{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530916 ALOGV("%s", __func__);
917 audio_route_apply_and_update_path(adev->audio_route,
918 "asrc-mode");
919 adev->asrc_mode_enabled = true;
920}
921
922static void disable_asrc_mode(struct audio_device *adev)
923{
924 ALOGV("%s", __func__);
925 audio_route_reset_and_update_path(adev->audio_route,
926 "asrc-mode");
927 adev->asrc_mode_enabled = false;
928}
929
930/*
931 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
932 * 44.1 or Native DSD backends are enabled for any of current use case.
933 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
934 * - Disable current mix path use case(Headphone backend) and re-enable it with
935 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
936 * e.g. Naitve DSD or Headphone 44.1 -> + 48
937 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530938static void check_and_set_asrc_mode(struct audio_device *adev,
939 struct audio_usecase *uc_info,
940 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530941{
942 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530943 int i, num_new_devices = 0;
944 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
945 /*
946 *Split snd device for new combo use case
947 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
948 */
949 if (platform_split_snd_device(adev->platform,
950 snd_device,
951 &num_new_devices,
952 split_new_snd_devices) == 0) {
953 for (i = 0; i < num_new_devices; i++)
954 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
955 } else {
956 int new_backend_idx = platform_get_backend_index(snd_device);
957 if (((new_backend_idx == HEADPHONE_BACKEND) ||
958 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
959 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
960 !adev->asrc_mode_enabled) {
961 struct listnode *node = NULL;
962 struct audio_usecase *uc = NULL;
963 struct stream_out *curr_out = NULL;
964 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
965 int i, num_devices, ret = 0;
966 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530967
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530968 list_for_each(node, &adev->usecase_list) {
969 uc = node_to_item(node, struct audio_usecase, list);
970 curr_out = (struct stream_out*) uc->stream.out;
971 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
972 /*
973 *Split snd device for existing combo use case
974 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
975 */
976 ret = platform_split_snd_device(adev->platform,
977 uc->out_snd_device,
978 &num_devices,
979 split_snd_devices);
980 if (ret < 0 || num_devices == 0) {
981 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
982 split_snd_devices[0] = uc->out_snd_device;
983 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800984 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530985 for (i = 0; i < num_devices; i++) {
986 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
987 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
988 if((new_backend_idx == HEADPHONE_BACKEND) &&
989 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
990 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
991 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
992 __func__);
993 enable_asrc_mode(adev);
994 break;
995 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
996 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
997 (usecase_backend_idx == HEADPHONE_BACKEND)) {
998 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
999 __func__);
1000 disable_audio_route(adev, uc);
1001 disable_snd_device(adev, uc->out_snd_device);
1002 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1003 if (new_backend_idx == DSD_NATIVE_BACKEND)
1004 audio_route_apply_and_update_path(adev->audio_route,
1005 "hph-true-highquality-mode");
1006 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1007 (curr_out->bit_width >= 24))
1008 audio_route_apply_and_update_path(adev->audio_route,
1009 "hph-highquality-mode");
1010 enable_asrc_mode(adev);
1011 enable_snd_device(adev, uc->out_snd_device);
1012 enable_audio_route(adev, uc);
1013 break;
1014 }
1015 }
1016 // reset split devices count
1017 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001018 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301019 if (adev->asrc_mode_enabled)
1020 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301021 }
1022 }
1023 }
1024}
1025
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001026static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1027 struct audio_effect_config effect_config,
1028 unsigned int param_value)
1029{
1030 char mixer_ctl_name[] = "Audio Effect";
1031 struct mixer_ctl *ctl;
1032 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001033 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001034
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001035 if (in == NULL) {
1036 ALOGE("%s: active input stream is NULL", __func__);
1037 return -EINVAL;
1038 }
1039
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001040 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1041 if (!ctl) {
1042 ALOGE("%s: Could not get mixer ctl - %s",
1043 __func__, mixer_ctl_name);
1044 return -EINVAL;
1045 }
1046
1047 set_values[0] = 1; //0:Rx 1:Tx
1048 set_values[1] = in->app_type_cfg.app_type;
1049 set_values[2] = (long)effect_config.module_id;
1050 set_values[3] = (long)effect_config.instance_id;
1051 set_values[4] = (long)effect_config.param_id;
1052 set_values[5] = param_value;
1053
1054 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1055
1056 return 0;
1057
1058}
1059
1060static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1061 int effect_type, unsigned int *param_value)
1062{
1063 int ret = 0;
1064 struct audio_effect_config other_effect_config;
1065 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001066 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001067
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001068 if (in == NULL) {
1069 ALOGE("%s: active input stream is NULL", __func__);
1070 return -EINVAL;
1071 }
1072
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001073 usecase = get_usecase_from_list(adev, in->usecase);
1074 if (!usecase)
1075 return -EINVAL;
1076
1077 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1078 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1079 if (ret < 0) {
1080 ALOGE("%s Failed to get effect params %d", __func__, ret);
1081 return ret;
1082 }
1083
1084 if (module_id == other_effect_config.module_id) {
1085 //Same module id for AEC/NS. Values need to be combined
1086 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1087 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1088 *param_value |= other_effect_config.param_value;
1089 }
1090 }
1091
1092 return ret;
1093}
1094
1095static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301096{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001097 struct audio_effect_config effect_config;
1098 struct audio_usecase *usecase = NULL;
1099 int ret = 0;
1100 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001101 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001102
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001103 if(!voice_extn_is_dynamic_ecns_enabled())
1104 return ENOSYS;
1105
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001106 if (!in) {
1107 ALOGE("%s: Invalid input stream", __func__);
1108 return -EINVAL;
1109 }
1110
1111 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1112
1113 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001114 if (usecase == NULL) {
1115 ALOGE("%s: Could not find the usecase (%d) in the list",
1116 __func__, in->usecase);
1117 return -EINVAL;
1118 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001119
1120 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1121 if (ret < 0) {
1122 ALOGE("%s Failed to get module id %d", __func__, ret);
1123 return ret;
1124 }
1125 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1126 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1127
1128 if(enable)
1129 param_value = effect_config.param_value;
1130
1131 /*Special handling for AEC & NS effects Param values need to be
1132 updated if module ids are same*/
1133
1134 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1135 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1136 if (ret < 0)
1137 return ret;
1138 }
1139
1140 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1141
1142 return ret;
1143}
1144
1145static void check_and_enable_effect(struct audio_device *adev)
1146{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001147 if(!voice_extn_is_dynamic_ecns_enabled())
1148 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001149
Eric Laurent637e2d42018-11-15 12:24:31 -08001150 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001151
Eric Laurent637e2d42018-11-15 12:24:31 -08001152 if (in != NULL && !in->standby) {
1153 if (in->enable_aec)
1154 enable_disable_effect(adev, EFFECT_AEC, true);
1155
1156 if (in->enable_ns &&
1157 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1158 enable_disable_effect(adev, EFFECT_NS, true);
1159 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001160 }
1161}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001162
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001163int pcm_ioctl(struct pcm *pcm, int request, ...)
1164{
1165 va_list ap;
1166 void * arg;
1167 int pcm_fd = *(int*)pcm;
1168
1169 va_start(ap, request);
1170 arg = va_arg(ap, void *);
1171 va_end(ap);
1172
1173 return ioctl(pcm_fd, request, arg);
1174}
1175
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001176int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001177 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001178{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001180 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301181 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301182 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001183 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301184 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001185
1186 if (usecase == NULL)
1187 return -EINVAL;
1188
1189 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1190
Carter Hsu2e429db2019-05-14 18:50:52 +08001191 if (usecase->type == PCM_CAPTURE) {
1192 struct stream_in *in = usecase->stream.in;
1193 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001194 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001195
1196 if (in) {
1197 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001198 list_init(&out_devices);
1199 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001200 struct listnode *node;
1201 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1202 USECASE_AUDIO_PLAYBACK_VOIP);
1203 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001204 assign_devices(&out_devices,
1205 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001206 } else if (adev->primary_output &&
1207 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001208 assign_devices(&out_devices,
1209 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001210 } else {
1211 list_for_each(node, &adev->usecase_list) {
1212 uinfo = node_to_item(node, struct audio_usecase, list);
1213 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001214 assign_devices(&out_devices,
1215 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001216 break;
1217 }
1218 }
1219 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001220
1221 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001222 in->ec_opened = true;
1223 }
1224 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001225 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1226 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1227 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001228 snd_device = usecase->in_snd_device;
1229 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001230 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001231 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001232
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001233#ifdef DS1_DOLBY_DAP_ENABLED
1234 audio_extn_dolby_set_dmid(adev);
1235 audio_extn_dolby_set_endpoint(adev);
1236#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001237 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001238 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301239 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001240 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001241 if (audio_extn_is_maxx_audio_enabled())
1242 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301243 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301244 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1245 out = usecase->stream.out;
1246 if (out && out->compr)
1247 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1248 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301249
1250 if (usecase->type == PCM_CAPTURE) {
1251 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001252 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301253 ALOGD("%s: set custom mtmx params v1", __func__);
1254 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1255 }
1256 } else {
1257 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1258 }
Manish Dewangan58229382017-02-02 15:48:41 +05301259
Andy Hung756ecc12018-10-19 17:47:12 -07001260 // we shouldn't truncate mixer_path
1261 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1262 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1263 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001264 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001265 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301266 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1267 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1268 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1269 if (parms) {
1270 audio_extn_fm_set_parameters(adev, parms);
1271 str_parms_destroy(parms);
1272 }
1273 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001274 ALOGV("%s: exit", __func__);
1275 return 0;
1276}
1277
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001278int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001279 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001281 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001282 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301283 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001284
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301285 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001286 return -EINVAL;
1287
1288 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301289 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001290 snd_device = usecase->in_snd_device;
1291 else
1292 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001293 // we shouldn't truncate mixer_path
1294 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1295 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1296 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001297 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001298 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001299 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001300 if (usecase->type == PCM_CAPTURE) {
1301 struct stream_in *in = usecase->stream.in;
1302 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001303 struct listnode out_devices;
1304 list_init(&out_devices);
1305 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001306 in->ec_opened = false;
1307 }
1308 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001309 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301310 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301311
1312 if (usecase->type == PCM_CAPTURE) {
1313 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001314 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301315 ALOGD("%s: reset custom mtmx params v1", __func__);
1316 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1317 }
1318 } else {
1319 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1320 }
1321
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001322 if ((usecase->type == PCM_PLAYBACK) &&
1323 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301324 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301325
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001326 ALOGV("%s: exit", __func__);
1327 return 0;
1328}
1329
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001330int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001331 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001332{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301333 int i, num_devices = 0;
1334 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001335 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1336
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001337 if (snd_device < SND_DEVICE_MIN ||
1338 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001339 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001340 return -EINVAL;
1341 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001342
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001343 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001344 ALOGE("%s: Invalid sound device returned", __func__);
1345 return -EINVAL;
1346 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001347
1348 adev->snd_dev_ref_cnt[snd_device]++;
1349
1350 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1351 (platform_split_snd_device(adev->platform,
1352 snd_device,
1353 &num_devices,
1354 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001355 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001356 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001357 return 0;
1358 }
1359
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001360 if (audio_extn_spkr_prot_is_enabled())
1361 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001362
Aalique Grahame22e49102018-12-18 14:23:57 -08001363 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1364
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001365 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1366 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001367 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1368 goto err;
1369 }
1370 audio_extn_dev_arbi_acquire(snd_device);
1371 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001372 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001373 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001374 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001375 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001376 } else if (platform_split_snd_device(adev->platform,
1377 snd_device,
1378 &num_devices,
1379 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301380 for (i = 0; i < num_devices; i++) {
1381 enable_snd_device(adev, new_snd_devices[i]);
1382 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001383 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001384 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001385 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301386
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301387
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001388 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1389 (audio_extn_a2dp_start_playback() < 0)) {
1390 ALOGE(" fail to configure A2dp Source control path ");
1391 goto err;
1392 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001393
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001394 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1395 (audio_extn_a2dp_start_capture() < 0)) {
1396 ALOGE(" fail to configure A2dp Sink control path ");
1397 goto err;
1398 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301399
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001400 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1401 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1402 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1403 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1404 ALOGE(" fail to configure sco control path ");
1405 goto err;
1406 }
Zhou Song12c29502019-03-16 10:37:18 +08001407 }
1408
Zhou Song331c8e52019-08-26 14:16:12 +08001409 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001410 /* due to the possibility of calibration overwrite between listen
1411 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001412 audio_extn_sound_trigger_update_device_status(snd_device,
1413 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301414 audio_extn_listen_update_device_status(snd_device,
1415 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001416 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001417 audio_extn_sound_trigger_update_device_status(snd_device,
1418 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301419 audio_extn_listen_update_device_status(snd_device,
1420 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001421 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001422 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001423 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001424 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301425
1426 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1427 !adev->native_playback_enabled &&
1428 audio_is_true_native_stream_active(adev)) {
1429 ALOGD("%s: %d: napb: enabling native mode in hardware",
1430 __func__, __LINE__);
1431 audio_route_apply_and_update_path(adev->audio_route,
1432 "true-native-mode");
1433 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301434 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301435 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1436 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001437 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001438 ALOGD("%s: init ec ref loopback", __func__);
1439 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1440 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001441 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001443err:
1444 adev->snd_dev_ref_cnt[snd_device]--;
1445 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446}
1447
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001448int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001449 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301451 int i, num_devices = 0;
1452 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001453 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1454
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001455 if (snd_device < SND_DEVICE_MIN ||
1456 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001457 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001458 return -EINVAL;
1459 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001460
1461 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1462 ALOGE("%s: Invalid sound device returned", __func__);
1463 return -EINVAL;
1464 }
1465
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001466 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1467 ALOGE("%s: device ref cnt is already 0", __func__);
1468 return -EINVAL;
1469 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001470
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001471 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001472
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001473
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001474 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001475 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301476
Aalique Grahame22e49102018-12-18 14:23:57 -08001477 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1478
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001479 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1480 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001481 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001482
1483 // when speaker device is disabled, reset swap.
1484 // will be renabled on usecase start
1485 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001486 } else if (platform_split_snd_device(adev->platform,
1487 snd_device,
1488 &num_devices,
1489 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301490 for (i = 0; i < num_devices; i++) {
1491 disable_snd_device(adev, new_snd_devices[i]);
1492 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001493 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001494 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001495 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001496 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001497
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001498 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301499 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001500 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001501 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001502 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001503 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301504 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001505 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301506 adev->native_playback_enabled) {
1507 ALOGD("%s: %d: napb: disabling native mode in hardware",
1508 __func__, __LINE__);
1509 audio_route_reset_and_update_path(adev->audio_route,
1510 "true-native-mode");
1511 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001512 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301513 adev->asrc_mode_enabled) {
1514 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301515 disable_asrc_mode(adev);
1516 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001517 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301518 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001519 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001520 ALOGD("%s: deinit ec ref loopback", __func__);
1521 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1522 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001523
1524 audio_extn_utils_release_snd_device(snd_device);
1525 } else {
1526 if (platform_split_snd_device(adev->platform,
1527 snd_device,
1528 &num_devices,
1529 new_snd_devices) == 0) {
1530 for (i = 0; i < num_devices; i++) {
1531 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1532 }
1533 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001534 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536 return 0;
1537}
1538
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001539/*
1540 legend:
1541 uc - existing usecase
1542 new_uc - new usecase
1543 d1, d11, d2 - SND_DEVICE enums
1544 a1, a2 - corresponding ANDROID device enums
1545 B1, B2 - backend strings
1546
1547case 1
1548 uc->dev d1 (a1) B1
1549 new_uc->dev d1 (a1), d2 (a2) B1, B2
1550
1551 resolution: disable and enable uc->dev on d1
1552
1553case 2
1554 uc->dev d1 (a1) B1
1555 new_uc->dev d11 (a1) B1
1556
1557 resolution: need to switch uc since d1 and d11 are related
1558 (e.g. speaker and voice-speaker)
1559 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1560
1561case 3
1562 uc->dev d1 (a1) B1
1563 new_uc->dev d2 (a2) B2
1564
1565 resolution: no need to switch uc
1566
1567case 4
1568 uc->dev d1 (a1) B1
1569 new_uc->dev d2 (a2) B1
1570
1571 resolution: disable enable uc-dev on d2 since backends match
1572 we cannot enable two streams on two different devices if they
1573 share the same backend. e.g. if offload is on speaker device using
1574 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1575 using the same backend, offload must also be switched to voice-handset.
1576
1577case 5
1578 uc->dev d1 (a1) B1
1579 new_uc->dev d1 (a1), d2 (a2) B1
1580
1581 resolution: disable enable uc-dev on d2 since backends match
1582 we cannot enable two streams on two different devices if they
1583 share the same backend.
1584
1585case 6
1586 uc->dev d1 (a1) B1
1587 new_uc->dev d2 (a1) B2
1588
1589 resolution: no need to switch
1590
1591case 7
1592 uc->dev d1 (a1), d2 (a2) B1, B2
1593 new_uc->dev d1 (a1) B1
1594
1595 resolution: no need to switch
1596
Zhou Song4ba65882018-07-09 14:48:07 +08001597case 8
1598 uc->dev d1 (a1) B1
1599 new_uc->dev d11 (a1), d2 (a2) B1, B2
1600 resolution: compared to case 1, for this case, d1 and d11 are related
1601 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301602
1603case 9
1604 uc->dev d1 (a1), d2(a2) B1 B2
1605 new_uc->dev d1 (a1), d22 (a2) B1, B2
1606 resolution: disable enable uc-dev on d2 since backends match
1607 we cannot enable two streams on two different devices if they
1608 share the same backend. This is special case for combo use case
1609 with a2dp and sco devices which uses same backend.
1610 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001611*/
1612static snd_device_t derive_playback_snd_device(void * platform,
1613 struct audio_usecase *uc,
1614 struct audio_usecase *new_uc,
1615 snd_device_t new_snd_device)
1616{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001617 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001618
1619 snd_device_t d1 = uc->out_snd_device;
1620 snd_device_t d2 = new_snd_device;
1621
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001622 list_init(&a1);
1623 list_init(&a2);
1624
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301625 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301626 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001627 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1628 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301629 break;
1630 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001631 assign_devices(&a1, &uc->stream.out->device_list);
1632 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301633 break;
1634 }
1635
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001636 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001637 if (!compare_devices(&a1, &a2) &&
1638 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001639 snd_device_t d3[2];
1640 int num_devices = 0;
1641 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001642 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001643 &num_devices,
1644 d3);
1645 if (ret < 0) {
1646 if (ret != -ENOSYS) {
1647 ALOGW("%s failed to split snd_device %d",
1648 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001649 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001650 }
1651 goto end;
1652 }
1653
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001654 if (platform_check_backends_match(d3[0], d3[1])) {
1655 return d2; // case 5
1656 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301657 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1658 platform_check_backends_match(d1, d2))
1659 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001660 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301661 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001662 // check if d1 is related to any of d3's
1663 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001664 return d1; // case 1
1665 else
1666 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001667 }
1668 } else {
1669 if (platform_check_backends_match(d1, d2)) {
1670 return d2; // case 2, 4
1671 } else {
1672 return d1; // case 6, 3
1673 }
1674 }
1675
1676end:
1677 return d2; // return whatever was calculated before.
1678}
1679
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001680static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301681 struct audio_usecase *uc_info,
1682 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001683{
1684 struct listnode *node;
1685 struct audio_usecase *usecase;
1686 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301687 snd_device_t uc_derive_snd_device;
1688 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001689 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1690 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001691 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301692 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001693 /*
1694 * This function is to make sure that all the usecases that are active on
1695 * the hardware codec backend are always routed to any one device that is
1696 * handled by the hardware codec.
1697 * For example, if low-latency and deep-buffer usecases are currently active
1698 * on speaker and out_set_parameters(headset) is received on low-latency
1699 * output, then we have to make sure deep-buffer is also switched to headset,
1700 * because of the limitation that both the devices cannot be enabled
1701 * at the same time as they share the same backend.
1702 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001703 /*
1704 * This call is to check if we need to force routing for a particular stream
1705 * If there is a backend configuration change for the device when a
1706 * new stream starts, then ADM needs to be closed and re-opened with the new
1707 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001708 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001709 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001710 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1711 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301712 /* For a2dp device reconfigure all active sessions
1713 * with new AFE encoder format based on a2dp state
1714 */
1715 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301716 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1717 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301718 audio_extn_a2dp_is_force_device_switch()) {
1719 force_routing = true;
1720 force_restart_session = true;
1721 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301722 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1723
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001724 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001725 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001726 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001727 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1728 switch_device[i] = false;
1729
1730 list_for_each(node, &adev->usecase_list) {
1731 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001732
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301733 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1734 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301735 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301736 platform_get_snd_device_name(usecase->out_snd_device),
1737 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301738 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1739 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301740 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1741 usecase, uc_info, snd_device);
1742 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001743 (is_codec_backend_out_device_type(&usecase->device_list) ||
1744 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1745 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1746 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1747 is_a2dp_out_device_type(&usecase->device_list) ||
1748 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301749 ((force_restart_session) ||
1750 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301751 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1752 __func__, use_case_table[usecase->id],
1753 platform_get_snd_device_name(usecase->out_snd_device));
1754 disable_audio_route(adev, usecase);
1755 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301756 /* Enable existing usecase on derived playback device */
1757 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301758 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301759 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001760 }
1761 }
1762
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301763 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1764 num_uc_to_switch);
1765
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001766 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001767 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001768
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301769 /* Make sure the previous devices to be disabled first and then enable the
1770 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001771 list_for_each(node, &adev->usecase_list) {
1772 usecase = node_to_item(node, struct audio_usecase, list);
1773 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001774 /* Check if output sound device to be switched can be split and if any
1775 of the split devices match with derived sound device */
1776 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1777 &num_devices, split_snd_devices) == 0) {
1778 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1779 for (i = 0; i < num_devices; i++) {
1780 /* Disable devices that do not match with derived sound device */
1781 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1782 disable_snd_device(adev, split_snd_devices[i]);
1783 }
1784 } else {
1785 disable_snd_device(adev, usecase->out_snd_device);
1786 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001787 }
1788 }
1789
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001790 list_for_each(node, &adev->usecase_list) {
1791 usecase = node_to_item(node, struct audio_usecase, list);
1792 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001793 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1794 &num_devices, split_snd_devices) == 0) {
1795 /* Enable derived sound device only if it does not match with
1796 one of the split sound devices. This is because the matching
1797 sound device was not disabled */
1798 bool should_enable = true;
1799 for (i = 0; i < num_devices; i++) {
1800 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1801 should_enable = false;
1802 break;
1803 }
1804 }
1805 if (should_enable)
1806 enable_snd_device(adev, derive_snd_device[usecase->id]);
1807 } else {
1808 enable_snd_device(adev, derive_snd_device[usecase->id]);
1809 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001810 }
1811 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001812
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001813 /* Re-route all the usecases on the shared backend other than the
1814 specified usecase to new snd devices */
1815 list_for_each(node, &adev->usecase_list) {
1816 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301817 /* Update the out_snd_device only before enabling the audio route */
1818 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301819 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301820 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301821 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301822 use_case_table[usecase->id],
1823 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001824 /* Update voc calibration before enabling VoIP route */
1825 if (usecase->type == VOIP_CALL)
1826 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001827 usecase->out_snd_device,
1828 platform_get_input_snd_device(
1829 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301830 &uc_info->device_list,
1831 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301832 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301833 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001834 out_set_voip_volume(&usecase->stream.out->stream,
1835 usecase->stream.out->volume_l,
1836 usecase->stream.out->volume_r);
1837 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301838 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001839 }
1840 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001841 }
1842}
1843
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301844static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001845 struct audio_usecase *uc_info,
1846 snd_device_t snd_device)
1847{
1848 struct listnode *node;
1849 struct audio_usecase *usecase;
1850 bool switch_device[AUDIO_USECASE_MAX];
1851 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001852 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001853 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001854
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301855 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1856 snd_device);
1857 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301858
1859 /*
1860 * Make sure out devices is checked against out codec backend device and
1861 * also in devices against in codec backend. Checking out device against in
1862 * codec backend or vice versa causes issues.
1863 */
1864 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001865 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001866 /*
1867 * This function is to make sure that all the active capture usecases
1868 * are always routed to the same input sound device.
1869 * For example, if audio-record and voice-call usecases are currently
1870 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1871 * is received for voice call then we have to make sure that audio-record
1872 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1873 * because of the limitation that two devices cannot be enabled
1874 * at the same time if they share the same backend.
1875 */
1876 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1877 switch_device[i] = false;
1878
1879 list_for_each(node, &adev->usecase_list) {
1880 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301881 /*
1882 * TODO: Enhance below condition to handle BT sco/USB multi recording
1883 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301884
1885 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1886 (usecase->in_snd_device != snd_device || force_routing));
1887 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1888 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1889 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001890 ((backend_check_cond &&
1891 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001892 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001893 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001894 is_single_device_type_equal(&usecase->device_list,
1895 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001896 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001897 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001898 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301899 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001900 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001901 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001902 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001903 switch_device[usecase->id] = true;
1904 num_uc_to_switch++;
1905 }
1906 }
1907
1908 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001909 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001910
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301911 /* Make sure the previous devices to be disabled first and then enable the
1912 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001913 list_for_each(node, &adev->usecase_list) {
1914 usecase = node_to_item(node, struct audio_usecase, list);
1915 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001916 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001917 }
1918 }
1919
1920 list_for_each(node, &adev->usecase_list) {
1921 usecase = node_to_item(node, struct audio_usecase, list);
1922 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001923 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001924 }
1925 }
1926
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001927 /* Re-route all the usecases on the shared backend other than the
1928 specified usecase to new snd devices */
1929 list_for_each(node, &adev->usecase_list) {
1930 usecase = node_to_item(node, struct audio_usecase, list);
1931 /* Update the in_snd_device only before enabling the audio route */
1932 if (switch_device[usecase->id] ) {
1933 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001934 if (usecase->type != VOICE_CALL) {
1935 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301936 if (usecase->type == VOIP_CALL) {
1937 snd_device_t voip_snd_device;
1938 voip_snd_device = platform_get_output_snd_device(adev->platform,
1939 uc_info->stream.out,
1940 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08001941 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301942 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08001943 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05301944 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05301945 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001946 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001947 }
1948 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001949 }
1950}
1951
Mingming Yin3a941d42016-02-17 18:08:05 -08001952static void reset_hdmi_sink_caps(struct stream_out *out) {
1953 int i = 0;
1954
1955 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1956 out->supported_channel_masks[i] = 0;
1957 }
1958 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1959 out->supported_formats[i] = 0;
1960 }
1961 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1962 out->supported_sample_rates[i] = 0;
1963 }
1964}
1965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001967static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968{
Mingming Yin3a941d42016-02-17 18:08:05 -08001969 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001970 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
1971 out->extconn.cs.controller,
1972 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973
Mingming Yin3a941d42016-02-17 18:08:05 -08001974 reset_hdmi_sink_caps(out);
1975
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001976 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08001977 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001978 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08001979 out->extconn.cs.stream);
1980 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001981 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001982 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001983 }
1984
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001985 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001987 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001988 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001989 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1990 case 6:
1991 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1992 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1993 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1994 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1995 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1996 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997 break;
1998 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001999 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002000 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001 break;
2002 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002003
2004 // check channel format caps
2005 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002006 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2007 out->extconn.cs.controller,
2008 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002009 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2010 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2011 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2012 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2013 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2014 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2015 }
2016
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002017 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2018 out->extconn.cs.controller,
2019 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002020 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2021 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2022 }
2023
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002024 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2025 out->extconn.cs.controller,
2026 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002027 ALOGV(":%s HDMI supports DTS format", __func__);
2028 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2029 }
2030
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002031 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2032 out->extconn.cs.controller,
2033 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002034 ALOGV(":%s HDMI supports DTS HD format", __func__);
2035 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2036 }
2037
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002038 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2039 out->extconn.cs.controller,
2040 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002041 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2042 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2043 }
2044
Mingming Yin3a941d42016-02-17 18:08:05 -08002045
2046 // check sample rate caps
2047 i = 0;
2048 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002049 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2050 out->extconn.cs.controller,
2051 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002052 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2053 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2054 }
2055 }
2056
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002057 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058}
2059
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002060static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2061 uint32_t *supported_sample_rates __unused,
2062 uint32_t max_rates __unused)
2063{
2064 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2065 supported_sample_rates,
2066 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302067 ssize_t i = 0;
2068
2069 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002070 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2071 supported_sample_rates[i]);
2072 }
2073 return count;
2074}
2075
2076static inline int read_usb_sup_channel_masks(bool is_playback,
2077 audio_channel_mask_t *supported_channel_masks,
2078 uint32_t max_masks)
2079{
2080 int channels = audio_extn_usb_get_max_channels(is_playback);
2081 int channel_count;
2082 uint32_t num_masks = 0;
2083 if (channels > MAX_HIFI_CHANNEL_COUNT)
2084 channels = MAX_HIFI_CHANNEL_COUNT;
2085
2086 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002087 // start from 2 channels as framework currently doesn't support mono.
2088 if (channels >= FCC_2) {
2089 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2090 }
2091 for (channel_count = FCC_2;
2092 channel_count <= channels && num_masks < max_masks;
2093 ++channel_count) {
2094 supported_channel_masks[num_masks++] =
2095 audio_channel_mask_for_index_assignment_from_count(channel_count);
2096 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002097 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002098 // For capture we report all supported channel masks from 1 channel up.
2099 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002100 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2101 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002102 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2103 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2104 if (channel_count <= FCC_2) {
2105 mask = audio_channel_in_mask_from_count(channel_count);
2106 supported_channel_masks[num_masks++] = mask;
2107 }
2108 const audio_channel_mask_t index_mask =
2109 audio_channel_mask_for_index_assignment_from_count(channel_count);
2110 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2111 supported_channel_masks[num_masks++] = index_mask;
2112 }
2113 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002114 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302115
vincenttewf51c94e2019-05-07 10:28:53 +08002116 for (size_t i = 0; i < num_masks; ++i) {
2117 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2118 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302119 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002120 return num_masks;
2121}
2122
2123static inline int read_usb_sup_formats(bool is_playback __unused,
2124 audio_format_t *supported_formats,
2125 uint32_t max_formats __unused)
2126{
2127 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2128 switch (bitwidth) {
2129 case 24:
2130 // XXX : usb.c returns 24 for s24 and s24_le?
2131 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2132 break;
2133 case 32:
2134 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2135 break;
2136 case 16:
2137 default :
2138 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2139 break;
2140 }
2141 ALOGV("%s: %s supported format %d", __func__,
2142 is_playback ? "P" : "C", bitwidth);
2143 return 1;
2144}
2145
2146static inline int read_usb_sup_params_and_compare(bool is_playback,
2147 audio_format_t *format,
2148 audio_format_t *supported_formats,
2149 uint32_t max_formats,
2150 audio_channel_mask_t *mask,
2151 audio_channel_mask_t *supported_channel_masks,
2152 uint32_t max_masks,
2153 uint32_t *rate,
2154 uint32_t *supported_sample_rates,
2155 uint32_t max_rates) {
2156 int ret = 0;
2157 int num_formats;
2158 int num_masks;
2159 int num_rates;
2160 int i;
2161
2162 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2163 max_formats);
2164 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2165 max_masks);
2166
2167 num_rates = read_usb_sup_sample_rates(is_playback,
2168 supported_sample_rates, max_rates);
2169
2170#define LUT(table, len, what, dflt) \
2171 for (i=0; i<len && (table[i] != what); i++); \
2172 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2173
2174 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2175 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2176 LUT(supported_sample_rates, num_rates, *rate, 0);
2177
2178#undef LUT
2179 return ret < 0 ? -EINVAL : 0; // HACK TBD
2180}
2181
Alexy Josephb1379942016-01-29 15:49:38 -08002182audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002183 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002184{
2185 struct audio_usecase *usecase;
2186 struct listnode *node;
2187
2188 list_for_each(node, &adev->usecase_list) {
2189 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002190 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002191 ALOGV("%s: usecase id %d", __func__, usecase->id);
2192 return usecase->id;
2193 }
2194 }
2195 return USECASE_INVALID;
2196}
2197
Alexy Josephb1379942016-01-29 15:49:38 -08002198struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002199 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002200{
2201 struct audio_usecase *usecase;
2202 struct listnode *node;
2203
2204 list_for_each(node, &adev->usecase_list) {
2205 usecase = node_to_item(node, struct audio_usecase, list);
2206 if (usecase->id == uc_id)
2207 return usecase;
2208 }
2209 return NULL;
2210}
2211
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302212/*
2213 * is a true native playback active
2214 */
2215bool audio_is_true_native_stream_active(struct audio_device *adev)
2216{
2217 bool active = false;
2218 int i = 0;
2219 struct listnode *node;
2220
2221 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2222 ALOGV("%s:napb: not in true mode or non hdphones device",
2223 __func__);
2224 active = false;
2225 goto exit;
2226 }
2227
2228 list_for_each(node, &adev->usecase_list) {
2229 struct audio_usecase *uc;
2230 uc = node_to_item(node, struct audio_usecase, list);
2231 struct stream_out *curr_out =
2232 (struct stream_out*) uc->stream.out;
2233
2234 if (curr_out && PCM_PLAYBACK == uc->type) {
2235 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2236 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2237 uc->id, curr_out->sample_rate,
2238 curr_out->bit_width,
2239 platform_get_snd_device_name(uc->out_snd_device));
2240
2241 if (is_offload_usecase(uc->id) &&
2242 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2243 active = true;
2244 ALOGD("%s:napb:native stream detected", __func__);
2245 }
2246 }
2247 }
2248exit:
2249 return active;
2250}
2251
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002252uint32_t adev_get_dsp_bit_width_enforce_mode()
2253{
2254 if (adev == NULL) {
2255 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2256 return 0;
2257 }
2258 return adev->dsp_bit_width_enforce_mode;
2259}
2260
2261static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2262{
2263 char value[PROPERTY_VALUE_MAX];
2264 int trial;
2265 uint32_t dsp_bit_width_enforce_mode = 0;
2266
2267 if (!mixer) {
2268 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2269 __func__);
2270 return 0;
2271 }
2272
2273 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2274 value, NULL) > 0) {
2275 trial = atoi(value);
2276 switch (trial) {
2277 case 16:
2278 dsp_bit_width_enforce_mode = 16;
2279 break;
2280 case 24:
2281 dsp_bit_width_enforce_mode = 24;
2282 break;
2283 case 32:
2284 dsp_bit_width_enforce_mode = 32;
2285 break;
2286 default:
2287 dsp_bit_width_enforce_mode = 0;
2288 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2289 break;
2290 }
2291 }
2292
2293 return dsp_bit_width_enforce_mode;
2294}
2295
2296static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2297 uint32_t enforce_mode,
2298 bool enable)
2299{
2300 struct mixer_ctl *ctl = NULL;
2301 const char *mixer_ctl_name = "ASM Bit Width";
2302 uint32_t asm_bit_width_mode = 0;
2303
2304 if (enforce_mode == 0) {
2305 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2306 return;
2307 }
2308
2309 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2310 if (!ctl) {
2311 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2312 __func__, mixer_ctl_name);
2313 return;
2314 }
2315
2316 if (enable)
2317 asm_bit_width_mode = enforce_mode;
2318 else
2319 asm_bit_width_mode = 0;
2320
2321 ALOGV("%s DSP bit width feature status is %d width=%d",
2322 __func__, enable, asm_bit_width_mode);
2323 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2324 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2325 asm_bit_width_mode);
2326
2327 return;
2328}
2329
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302330/*
2331 * if native DSD playback active
2332 */
2333bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2334{
2335 bool active = false;
2336 struct listnode *node = NULL;
2337 struct audio_usecase *uc = NULL;
2338 struct stream_out *curr_out = NULL;
2339
2340 list_for_each(node, &adev->usecase_list) {
2341 uc = node_to_item(node, struct audio_usecase, list);
2342 curr_out = (struct stream_out*) uc->stream.out;
2343
2344 if (curr_out && PCM_PLAYBACK == uc->type &&
2345 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2346 active = true;
2347 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302348 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302349 }
2350 }
2351 return active;
2352}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302353
2354static bool force_device_switch(struct audio_usecase *usecase)
2355{
2356 bool ret = false;
2357 bool is_it_true_mode = false;
2358
Zhou Song30f2c3e2018-02-08 14:02:15 +08002359 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302360 usecase->type == TRANSCODE_LOOPBACK_RX ||
2361 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002362 return false;
2363 }
2364
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002365 if(usecase->stream.out == NULL) {
2366 ALOGE("%s: stream.out is NULL", __func__);
2367 return false;
2368 }
2369
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302370 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002371 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002372 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2373 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302374 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2375 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2376 (!is_it_true_mode && adev->native_playback_enabled)){
2377 ret = true;
2378 ALOGD("napb: time to toggle native mode");
2379 }
2380 }
2381
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302382 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302383 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2384 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002385 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302386 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302387 ALOGD("Force a2dp device switch to update new encoder config");
2388 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002389 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302390
Florian Pfister1a84f312018-07-19 14:38:18 +02002391 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302392 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2393 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002394 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302395 return ret;
2396}
2397
Aalique Grahame22e49102018-12-18 14:23:57 -08002398static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2399{
2400 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2401}
2402
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302403bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2404{
2405 bool ret=false;
2406 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002407 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2408 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302409 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2410 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002411 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302412 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002413 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2414 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302415 ret = true;
2416
2417 return ret;
2418}
2419
2420bool is_a2dp_device(snd_device_t out_snd_device)
2421{
2422 bool ret=false;
2423 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2424 ret = true;
2425
2426 return ret;
2427}
2428
2429bool is_bt_soc_on(struct audio_device *adev)
2430{
2431 struct mixer_ctl *ctl;
2432 char *mixer_ctl_name = "BT SOC status";
2433 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2434 bool bt_soc_status = true;
2435 if (!ctl) {
2436 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2437 __func__, mixer_ctl_name);
2438 /*This is to ensure we dont break targets which dont have the kernel change*/
2439 return true;
2440 }
2441 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2442 ALOGD("BT SOC status: %d",bt_soc_status);
2443 return bt_soc_status;
2444}
2445
Zhou Song331c8e52019-08-26 14:16:12 +08002446static int configure_btsco_sample_rate(snd_device_t snd_device)
2447{
2448 struct mixer_ctl *ctl = NULL;
2449 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2450 char *rate_str = NULL;
2451 bool is_rx_dev = true;
2452
2453 if (is_btsco_device(snd_device, snd_device)) {
2454 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2455 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2456 if (!ctl_sr_tx || !ctl_sr_rx) {
2457 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2458 if (!ctl_sr)
2459 return -ENOSYS;
2460 }
2461
2462 switch (snd_device) {
2463 case SND_DEVICE_OUT_BT_SCO:
2464 rate_str = "KHZ_8";
2465 break;
2466 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2467 case SND_DEVICE_IN_BT_SCO_MIC:
2468 rate_str = "KHZ_8";
2469 is_rx_dev = false;
2470 break;
2471 case SND_DEVICE_OUT_BT_SCO_WB:
2472 rate_str = "KHZ_16";
2473 break;
2474 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2475 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2476 rate_str = "KHZ_16";
2477 is_rx_dev = false;
2478 break;
2479 default:
2480 return 0;
2481 }
2482
2483 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2484 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2485 return -ENOSYS;
2486 }
2487 return 0;
2488}
2489
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302490int out_standby_l(struct audio_stream *stream);
2491
Eric Laurent637e2d42018-11-15 12:24:31 -08002492struct stream_in *adev_get_active_input(const struct audio_device *adev)
2493{
2494 struct listnode *node;
2495 struct stream_in *last_active_in = NULL;
2496
2497 /* Get last added active input.
2498 * TODO: We may use a priority mechanism to pick highest priority active source */
2499 list_for_each(node, &adev->usecase_list)
2500 {
2501 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2502 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2503 last_active_in = usecase->stream.in;
2504 }
2505
2506 return last_active_in;
2507}
2508
2509struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2510{
2511 struct listnode *node;
2512
2513 /* First check active inputs with voice communication source and then
2514 * any input if audio mode is in communication */
2515 list_for_each(node, &adev->usecase_list)
2516 {
2517 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2518 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2519 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2520 return usecase->stream.in;
2521 }
2522 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2523 return adev_get_active_input(adev);
2524
2525 return NULL;
2526}
2527
Carter Hsu2e429db2019-05-14 18:50:52 +08002528/*
2529 * Aligned with policy.h
2530 */
2531static inline int source_priority(int inputSource)
2532{
2533 switch (inputSource) {
2534 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2535 return 9;
2536 case AUDIO_SOURCE_CAMCORDER:
2537 return 8;
2538 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2539 return 7;
2540 case AUDIO_SOURCE_UNPROCESSED:
2541 return 6;
2542 case AUDIO_SOURCE_MIC:
2543 return 5;
2544 case AUDIO_SOURCE_ECHO_REFERENCE:
2545 return 4;
2546 case AUDIO_SOURCE_FM_TUNER:
2547 return 3;
2548 case AUDIO_SOURCE_VOICE_RECOGNITION:
2549 return 2;
2550 case AUDIO_SOURCE_HOTWORD:
2551 return 1;
2552 default:
2553 break;
2554 }
2555 return 0;
2556}
2557
2558static struct stream_in *get_priority_input(struct audio_device *adev)
2559{
2560 struct listnode *node;
2561 struct audio_usecase *usecase;
2562 int last_priority = 0, priority;
2563 struct stream_in *priority_in = NULL;
2564 struct stream_in *in;
2565
2566 list_for_each(node, &adev->usecase_list) {
2567 usecase = node_to_item(node, struct audio_usecase, list);
2568 if (usecase->type == PCM_CAPTURE) {
2569 in = usecase->stream.in;
2570 if (!in)
2571 continue;
2572 priority = source_priority(in->source);
2573
2574 if (priority > last_priority) {
2575 last_priority = priority;
2576 priority_in = in;
2577 }
2578 }
2579 }
2580 return priority_in;
2581}
2582
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002583int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002585 snd_device_t out_snd_device = SND_DEVICE_NONE;
2586 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002587 struct audio_usecase *usecase = NULL;
2588 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002589 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002590 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302591 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002592 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002593 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302595 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2596
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002597 usecase = get_usecase_from_list(adev, uc_id);
2598 if (usecase == NULL) {
2599 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2600 return -EINVAL;
2601 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002603 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002604 (usecase->type == VOIP_CALL) ||
2605 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302606 if(usecase->stream.out == NULL) {
2607 ALOGE("%s: stream.out is NULL", __func__);
2608 return -EINVAL;
2609 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002610 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002611 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2612 uc_id);
2613 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2614 uc_id);
2615 } else {
2616 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302617 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002618 in_snd_device = platform_get_input_snd_device(adev->platform,
2619 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302620 &usecase->stream.out->device_list,
2621 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002622 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002623 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302624 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302625 if (usecase->stream.inout == NULL) {
2626 ALOGE("%s: stream.inout is NULL", __func__);
2627 return -EINVAL;
2628 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002629 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302630 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2631 stream_out.format = usecase->stream.inout->out_config.format;
2632 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302633 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002634 assign_devices(&usecase->device_list,
2635 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302636 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2637 if (usecase->stream.inout == NULL) {
2638 ALOGE("%s: stream.inout is NULL", __func__);
2639 return -EINVAL;
2640 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302641 struct listnode out_devices;
2642 list_init(&out_devices);
2643 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2644 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002645 assign_devices(&usecase->device_list,
2646 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002647 } else {
2648 /*
2649 * If the voice call is active, use the sound devices of voice call usecase
2650 * so that it would not result any device switch. All the usecases will
2651 * be switched to new device when select_devices() is called for voice call
2652 * usecase. This is to avoid switching devices for voice call when
2653 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002654 * choose voice call device only if the use case device is
2655 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002656 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002657 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002658 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002659 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002660 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2661 is_codec_backend_out_device_type(&usecase->device_list)) ||
2662 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2663 is_codec_backend_in_device_type(&usecase->device_list)) ||
2664 is_single_device_type_equal(&vc_usecase->device_list,
2665 AUDIO_DEVICE_OUT_HEARING_AID) ||
2666 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002667 AUDIO_DEVICE_IN_VOICE_CALL) ||
2668 (is_single_device_type_equal(&usecase->device_list,
2669 AUDIO_DEVICE_IN_USB_HEADSET) &&
2670 is_single_device_type_equal(&vc_usecase->device_list,
2671 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002672 in_snd_device = vc_usecase->in_snd_device;
2673 out_snd_device = vc_usecase->out_snd_device;
2674 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002675 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002676 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002677 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002678 if ((voip_usecase != NULL) &&
2679 (usecase->type == PCM_PLAYBACK) &&
2680 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002681 out_snd_device_backend_match = platform_check_backends_match(
2682 voip_usecase->out_snd_device,
2683 platform_get_output_snd_device(
2684 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302685 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002686 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002687 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2688 (is_codec_backend_out_device_type(&usecase->device_list) ||
2689 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002690 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002691 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002692 in_snd_device = voip_usecase->in_snd_device;
2693 out_snd_device = voip_usecase->out_snd_device;
2694 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002695 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002696 hfp_ucid = audio_extn_hfp_get_usecase();
2697 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002698 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002699 in_snd_device = hfp_usecase->in_snd_device;
2700 out_snd_device = hfp_usecase->out_snd_device;
2701 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002702 }
2703 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302704 if (usecase->stream.out == NULL) {
2705 ALOGE("%s: stream.out is NULL", __func__);
2706 return -EINVAL;
2707 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002708 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002709 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002710 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002711 struct stream_out *voip_out = adev->primary_output;
2712 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002713 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002714 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2715 else
2716 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302717 usecase->stream.out,
2718 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002719 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002720
Eric Laurent637e2d42018-11-15 12:24:31 -08002721 if (voip_usecase)
2722 voip_out = voip_usecase->stream.out;
2723
2724 if (usecase->stream.out == voip_out && voip_in != NULL)
2725 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002726 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002727 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302728 if (usecase->stream.in == NULL) {
2729 ALOGE("%s: stream.in is NULL", __func__);
2730 return -EINVAL;
2731 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002732 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002733 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002734 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002735 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002736 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002737 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002738
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002739 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002740 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002741 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2742 USECASE_AUDIO_PLAYBACK_VOIP);
2743
Carter Hsu2e429db2019-05-14 18:50:52 +08002744 usecase->stream.in->enable_ec_port = false;
2745
Zhou Song62ea0282020-03-22 19:53:01 +08002746 bool is_ha_usecase = adev->ha_proxy_enable ?
2747 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2748 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2749 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002750 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002751 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002752 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002753 } else if (adev->primary_output &&
2754 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002755 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002756 } else {
2757 /* forcing speaker o/p device to get matching i/p pair
2758 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002759 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002760 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002761 priority_in = voip_in;
2762 } else {
2763 /* get the input with the highest priority source*/
2764 priority_in = get_priority_input(adev);
2765
2766 if (!priority_in)
2767 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002768 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002769
Eric Laurent637e2d42018-11-15 12:24:31 -08002770 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002771 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302772 &out_devices,
2773 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002774 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002775 }
2776 }
2777
2778 if (out_snd_device == usecase->out_snd_device &&
2779 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302780
2781 if (!force_device_switch(usecase))
2782 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783 }
2784
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002785 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002786 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002787 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002788 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2789 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302790 }
2791
Aalique Grahame22e49102018-12-18 14:23:57 -08002792 if (out_snd_device != SND_DEVICE_NONE &&
2793 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2794 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2795 __func__,
2796 use_case_table[uc_id],
2797 adev->last_logged_snd_device[uc_id][0],
2798 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2799 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2800 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2801 -1,
2802 out_snd_device,
2803 platform_get_snd_device_name(out_snd_device),
2804 platform_get_snd_device_acdb_id(out_snd_device));
2805 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2806 }
2807 if (in_snd_device != SND_DEVICE_NONE &&
2808 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2809 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2810 __func__,
2811 use_case_table[uc_id],
2812 adev->last_logged_snd_device[uc_id][1],
2813 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2814 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2815 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2816 -1,
2817 in_snd_device,
2818 platform_get_snd_device_name(in_snd_device),
2819 platform_get_snd_device_acdb_id(in_snd_device));
2820 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2821 }
2822
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824 /*
2825 * Limitation: While in call, to do a device switch we need to disable
2826 * and enable both RX and TX devices though one of them is same as current
2827 * device.
2828 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002829 if ((usecase->type == VOICE_CALL) &&
2830 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2831 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002832 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002833 }
2834
2835 if (((usecase->type == VOICE_CALL) ||
2836 (usecase->type == VOIP_CALL)) &&
2837 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2838 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302839 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002840 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002841 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002842
2843 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302844 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002845 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002846 }
2847
Aalique Grahame22e49102018-12-18 14:23:57 -08002848 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2849 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002850 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302851 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002852 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2853 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2854 else
2855 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302856 }
2857
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002858 /* Disable current sound devices */
2859 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002860 disable_audio_route(adev, usecase);
2861 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002862 }
2863
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002864 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002865 disable_audio_route(adev, usecase);
2866 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867 }
2868
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002869 /* Applicable only on the targets that has external modem.
2870 * New device information should be sent to modem before enabling
2871 * the devices to reduce in-call device switch time.
2872 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002873 if ((usecase->type == VOICE_CALL) &&
2874 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2875 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002876 status = platform_switch_voice_call_enable_device_config(adev->platform,
2877 out_snd_device,
2878 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002879 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002880
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002881 /* Enable new sound devices */
2882 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002883 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302884 if (platform_check_codec_asrc_support(adev->platform))
2885 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002886 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887 }
2888
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002889 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302890 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002891 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002892 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002893
Avinash Vaish71a8b972014-07-24 15:36:33 +05302894 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002895 status = platform_switch_voice_call_device_post(adev->platform,
2896 out_snd_device,
2897 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302898 enable_audio_route_for_voice_usecases(adev, usecase);
2899 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002900
sangwoo170731f2013-06-08 15:36:36 +09002901 usecase->in_snd_device = in_snd_device;
2902 usecase->out_snd_device = out_snd_device;
2903
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302904 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2905 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302906 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002907 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002908 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002909 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2910 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2911 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2912 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2913 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2914 /*
2915 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2916 * configured device sample rate, if not update the COPP rate to be equal to the
2917 * device sample rate, else open COPP at stream sample rate
2918 */
2919 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2920 usecase->stream.out->sample_rate,
2921 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302922 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302923 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2924 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302925 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002926 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2927 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2928 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2929 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002930 }
2931 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002932
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002933 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002934
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002935 /* If input stream is already running then effect needs to be
2936 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002937 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002938 check_and_enable_effect(adev);
2939
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002940 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002941 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302942 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002943 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2944
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002945 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302946 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002947 voice_extn_compress_voip_is_started(adev))
2948 voice_set_sidetone(adev, out_snd_device, true);
2949 }
2950
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002951 /* Applicable only on the targets that has external modem.
2952 * Enable device command should be sent to modem only after
2953 * enabling voice call mixer controls
2954 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002955 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002956 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2957 out_snd_device,
2958 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302959
2960 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002961 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302962 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002963 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302964 if (is_bt_soc_on(adev) == false){
2965 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002966 if (in->pcm != NULL)
2967 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302968 }
2969 }
2970 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2971 && usecase->stream.out->started) {
2972 if (is_bt_soc_on(adev) == false) {
2973 ALOGD("BT SCO/A2DP disconnected while in connection");
2974 out_standby_l(&usecase->stream.out->stream.common);
2975 }
2976 }
2977 } else if ((usecase->stream.out != NULL) &&
2978 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302979 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2980 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08002981 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302982 usecase->stream.out->started) {
2983 if (is_bt_soc_on(adev) == false) {
2984 ALOGD("BT SCO/A2dp disconnected while in connection");
2985 out_standby_l(&usecase->stream.out->stream.common);
2986 }
2987 }
2988 }
2989
Yung Ti Su70cb8242018-06-22 17:38:47 +08002990 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002991 struct stream_out *voip_out = voip_usecase->stream.out;
2992 audio_extn_utils_send_app_type_gain(adev,
2993 voip_out->app_type_cfg.app_type,
2994 &voip_out->app_type_cfg.gain[0]);
2995 }
2996
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302997 ALOGD("%s: done",__func__);
2998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 return status;
3000}
3001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002static int stop_input_stream(struct stream_in *in)
3003{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303004 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303006
3007 if (in == NULL) {
3008 ALOGE("%s: stream_in ptr is NULL", __func__);
3009 return -EINVAL;
3010 }
3011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003013 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014
Eric Laurent994a6932013-07-17 11:51:42 -07003015 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003016 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 uc_info = get_usecase_from_list(adev, in->usecase);
3018 if (uc_info == NULL) {
3019 ALOGE("%s: Could not find the usecase (%d) in the list",
3020 __func__, in->usecase);
3021 return -EINVAL;
3022 }
3023
Carter Hsu2e429db2019-05-14 18:50:52 +08003024 priority_in = get_priority_input(adev);
3025
Derek Chenea197282019-01-07 17:35:01 -08003026 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3027 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003028
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003029 /* Close in-call recording streams */
3030 voice_check_and_stop_incall_rec_usecase(adev, in);
3031
Eric Laurent150dbfe2013-02-27 14:31:02 -08003032 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003033 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003034
3035 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003036 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003038 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303039 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3040
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003041 list_remove(&uc_info->list);
3042 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043
Carter Hsu2e429db2019-05-14 18:50:52 +08003044 if (priority_in == in) {
3045 priority_in = get_priority_input(adev);
3046 if (priority_in)
3047 select_devices(adev, priority_in->usecase);
3048 }
3049
Vatsal Buchac09ae062018-11-14 13:25:08 +05303050 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003051 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 return ret;
3053}
3054
3055int start_input_stream(struct stream_in *in)
3056{
3057 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003058 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303060
3061 if (in == NULL) {
3062 ALOGE("%s: stream_in ptr is NULL", __func__);
3063 return -EINVAL;
3064 }
3065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003067 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003068 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069
Mingming Yin2664a5b2015-09-03 10:53:11 -07003070 if (get_usecase_from_list(adev, usecase) == NULL)
3071 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303072 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3073 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003074
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303075 if (CARD_STATUS_OFFLINE == in->card_status||
3076 CARD_STATUS_OFFLINE == adev->card_status) {
3077 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303078 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303079 goto error_config;
3080 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303081
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003082 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303083 if (!adev->bt_sco_on) {
3084 ALOGE("%s: SCO profile is not ready, return error", __func__);
3085 ret = -EIO;
3086 goto error_config;
3087 }
3088 }
3089
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003090 /* Check if source matches incall recording usecase criteria */
3091 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3092 if (ret)
3093 goto error_config;
3094 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003095 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3096
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303097 if (audio_extn_cin_attached_usecase(in))
3098 audio_extn_cin_acquire_usecase(in);
3099
Mingming Yin2664a5b2015-09-03 10:53:11 -07003100 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3101 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3102 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003103 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003104 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003105
Eric Laurentb23d5282013-05-14 15:27:20 -07003106 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107 if (in->pcm_device_id < 0) {
3108 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3109 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003110 ret = -EINVAL;
3111 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003115
3116 if (!uc_info) {
3117 ret = -ENOMEM;
3118 goto error_config;
3119 }
3120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121 uc_info->id = in->usecase;
3122 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003123 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003124 list_init(&uc_info->device_list);
3125 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003126 uc_info->in_snd_device = SND_DEVICE_NONE;
3127 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003129 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003130 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303131 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3132 adev->perf_lock_opts,
3133 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003134 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135
Derek Chenea197282019-01-07 17:35:01 -08003136 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3137 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003138
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303139 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3140
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303141 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303142 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303143 if (ret)
3144 goto error_open;
3145 else
3146 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003147 }
3148
Haynes Mathew George16081042017-05-31 17:16:49 -07003149 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003150 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003151 ALOGE("%s: pcm stream not ready", __func__);
3152 goto error_open;
3153 }
3154 ret = pcm_start(in->pcm);
3155 if (ret < 0) {
3156 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3157 goto error_open;
3158 }
3159 } else {
3160 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3161 unsigned int pcm_open_retry_count = 0;
3162
Zhou Song62ea0282020-03-22 19:53:01 +08003163 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3164 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003165 flags |= PCM_MMAP | PCM_NOIRQ;
3166 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3167 } else if (in->realtime) {
3168 flags |= PCM_MMAP | PCM_NOIRQ;
3169 }
3170
Garmond Leunge2433c32017-09-28 21:51:22 -07003171 if (audio_extn_ffv_get_stream() == in) {
3172 ALOGD("%s: ffv stream, update pcm config", __func__);
3173 audio_extn_ffv_update_pcm_config(&config);
3174 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003175 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3176 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3177
3178 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003179 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003180 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003181 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003182 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303183 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303184 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3185 adev->card_status = CARD_STATUS_OFFLINE;
3186 in->card_status = CARD_STATUS_OFFLINE;
3187 ret = -EIO;
3188 goto error_open;
3189 }
3190
Haynes Mathew George16081042017-05-31 17:16:49 -07003191 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3192 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3193 if (in->pcm != NULL) {
3194 pcm_close(in->pcm);
3195 in->pcm = NULL;
3196 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003197 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003198 ret = -EIO;
3199 goto error_open;
3200 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003201 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003202 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3203 continue;
3204 }
3205 break;
3206 }
3207
3208 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003209 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003210 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003211 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003212 if (ret < 0) {
3213 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3214 pcm_close(in->pcm);
3215 in->pcm = NULL;
3216 goto error_open;
3217 }
3218 register_in_stream(in);
3219 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003220 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003221 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003222 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003223 if (ret < 0) {
3224 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003225 pcm_close(in->pcm);
3226 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003227 goto error_open;
3228 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003229 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003230 }
3231
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003232 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003233 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3234 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003235
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003236 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303237 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3238
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303239done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003240 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303241 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003242 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303243 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003244 return ret;
3245
3246error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003247 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303248 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003250
Eric Laurentc8400632013-02-14 19:04:54 -08003251error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303252 /*
3253 * sleep 50ms to allow sufficient time for kernel
3254 * drivers to recover incases like SSR.
3255 */
3256 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003257 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303258 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003259 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260}
3261
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003262void lock_input_stream(struct stream_in *in)
3263{
3264 pthread_mutex_lock(&in->pre_lock);
3265 pthread_mutex_lock(&in->lock);
3266 pthread_mutex_unlock(&in->pre_lock);
3267}
3268
3269void lock_output_stream(struct stream_out *out)
3270{
3271 pthread_mutex_lock(&out->pre_lock);
3272 pthread_mutex_lock(&out->lock);
3273 pthread_mutex_unlock(&out->pre_lock);
3274}
3275
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003276/* must be called with out->lock locked */
3277static int send_offload_cmd_l(struct stream_out* out, int command)
3278{
3279 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3280
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003281 if (!cmd) {
3282 ALOGE("failed to allocate mem for command 0x%x", command);
3283 return -ENOMEM;
3284 }
3285
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003286 ALOGVV("%s %d", __func__, command);
3287
3288 cmd->cmd = command;
3289 list_add_tail(&out->offload_cmd_list, &cmd->node);
3290 pthread_cond_signal(&out->offload_cond);
3291 return 0;
3292}
3293
3294/* must be called iwth out->lock locked */
3295static void stop_compressed_output_l(struct stream_out *out)
3296{
3297 out->offload_state = OFFLOAD_STATE_IDLE;
3298 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003299 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003300 if (out->compr != NULL) {
3301 compress_stop(out->compr);
3302 while (out->offload_thread_blocked) {
3303 pthread_cond_wait(&out->cond, &out->lock);
3304 }
3305 }
3306}
3307
Varun Balaraje49253e2017-07-06 19:48:56 +05303308bool is_interactive_usecase(audio_usecase_t uc_id)
3309{
3310 unsigned int i;
3311 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3312 if (uc_id == interactive_usecases[i])
3313 return true;
3314 }
3315 return false;
3316}
3317
3318static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3319{
3320 audio_usecase_t ret_uc = USECASE_INVALID;
3321 unsigned int intract_uc_index;
3322 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3323
3324 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3325 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3326 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3327 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3328 ret_uc = interactive_usecases[intract_uc_index];
3329 break;
3330 }
3331 }
3332
3333 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3334 return ret_uc;
3335}
3336
3337static void free_interactive_usecase(struct audio_device *adev,
3338 audio_usecase_t uc_id)
3339{
3340 unsigned int interact_uc_index;
3341 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3342
3343 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3344 if (interactive_usecases[interact_uc_index] == uc_id) {
3345 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3346 break;
3347 }
3348 }
3349 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3350}
3351
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003352bool is_offload_usecase(audio_usecase_t uc_id)
3353{
3354 unsigned int i;
3355 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3356 if (uc_id == offload_usecases[i])
3357 return true;
3358 }
3359 return false;
3360}
3361
Dhananjay Kumarac341582017-02-23 23:42:25 +05303362static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003363{
vivek mehta446c3962015-09-14 10:57:35 -07003364 audio_usecase_t ret_uc = USECASE_INVALID;
3365 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003366 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003367 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303368 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003369 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3370 else
3371 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003372
vivek mehta446c3962015-09-14 10:57:35 -07003373 pthread_mutex_lock(&adev->lock);
3374 if (get_usecase_from_list(adev, ret_uc) != NULL)
3375 ret_uc = USECASE_INVALID;
3376 pthread_mutex_unlock(&adev->lock);
3377
3378 return ret_uc;
3379 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003380
3381 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003382 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3383 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3384 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3385 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003386 break;
3387 }
3388 }
vivek mehta446c3962015-09-14 10:57:35 -07003389
3390 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3391 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003392}
3393
3394static void free_offload_usecase(struct audio_device *adev,
3395 audio_usecase_t uc_id)
3396{
vivek mehta446c3962015-09-14 10:57:35 -07003397 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003398 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003399
3400 if (!adev->multi_offload_enable)
3401 return;
3402
3403 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3404 if (offload_usecases[offload_uc_index] == uc_id) {
3405 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003406 break;
3407 }
3408 }
3409 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3410}
3411
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003412static void *offload_thread_loop(void *context)
3413{
3414 struct stream_out *out = (struct stream_out *) context;
3415 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003416 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003417
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003418 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003419 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003420 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3421
3422 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003423 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003424 out->offload_state = OFFLOAD_STATE_IDLE;
3425 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003426 for (;;) {
3427 struct offload_cmd *cmd = NULL;
3428 stream_callback_event_t event;
3429 bool send_callback = false;
3430
3431 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3432 __func__, list_empty(&out->offload_cmd_list),
3433 out->offload_state);
3434 if (list_empty(&out->offload_cmd_list)) {
3435 ALOGV("%s SLEEPING", __func__);
3436 pthread_cond_wait(&out->offload_cond, &out->lock);
3437 ALOGV("%s RUNNING", __func__);
3438 continue;
3439 }
3440
3441 item = list_head(&out->offload_cmd_list);
3442 cmd = node_to_item(item, struct offload_cmd, node);
3443 list_remove(item);
3444
3445 ALOGVV("%s STATE %d CMD %d out->compr %p",
3446 __func__, out->offload_state, cmd->cmd, out->compr);
3447
3448 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3449 free(cmd);
3450 break;
3451 }
3452
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003453 // allow OFFLOAD_CMD_ERROR reporting during standby
3454 // this is needed to handle failures during compress_open
3455 // Note however that on a pause timeout, the stream is closed
3456 // and no offload usecase will be active. Therefore this
3457 // special case is needed for compress_open failures alone
3458 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3459 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003460 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003461 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003462 pthread_cond_signal(&out->cond);
3463 continue;
3464 }
3465 out->offload_thread_blocked = true;
3466 pthread_mutex_unlock(&out->lock);
3467 send_callback = false;
3468 switch(cmd->cmd) {
3469 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003470 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003471 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003472 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003473 send_callback = true;
3474 event = STREAM_CBK_EVENT_WRITE_READY;
3475 break;
3476 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003477 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303478 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003479 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303480 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003481 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303482 if (ret < 0)
3483 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303484 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303485 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003486 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003487 else
3488 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003489 if (-ENETRESET != ret && !(-EINTR == ret &&
3490 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303491 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303492 pthread_mutex_lock(&out->lock);
3493 out->send_new_metadata = 1;
3494 out->send_next_track_params = true;
3495 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303496 event = STREAM_CBK_EVENT_DRAIN_READY;
3497 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3498 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303499 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003500 break;
3501 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003502 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003503 ret = compress_drain(out->compr);
3504 ALOGD("copl(%p):out of compress_drain", out);
3505 // EINTR check avoids drain interruption due to SSR
3506 if (-ENETRESET != ret && !(-EINTR == ret &&
3507 CARD_STATUS_OFFLINE == out->card_status)) {
3508 send_callback = true;
3509 event = STREAM_CBK_EVENT_DRAIN_READY;
3510 } else
3511 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303513 case OFFLOAD_CMD_ERROR:
3514 ALOGD("copl(%p): sending error callback to AF", out);
3515 send_callback = true;
3516 event = STREAM_CBK_EVENT_ERROR;
3517 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003518 default:
3519 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3520 break;
3521 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003522 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003523 out->offload_thread_blocked = false;
3524 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003525 if (send_callback && out->client_callback) {
3526 ALOGVV("%s: sending client_callback event %d", __func__, event);
3527 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003528 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003529 free(cmd);
3530 }
3531
3532 pthread_cond_signal(&out->cond);
3533 while (!list_empty(&out->offload_cmd_list)) {
3534 item = list_head(&out->offload_cmd_list);
3535 list_remove(item);
3536 free(node_to_item(item, struct offload_cmd, node));
3537 }
3538 pthread_mutex_unlock(&out->lock);
3539
3540 return NULL;
3541}
3542
3543static int create_offload_callback_thread(struct stream_out *out)
3544{
3545 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3546 list_init(&out->offload_cmd_list);
3547 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3548 offload_thread_loop, out);
3549 return 0;
3550}
3551
3552static int destroy_offload_callback_thread(struct stream_out *out)
3553{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003554 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003555 stop_compressed_output_l(out);
3556 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3557
3558 pthread_mutex_unlock(&out->lock);
3559 pthread_join(out->offload_thread, (void **) NULL);
3560 pthread_cond_destroy(&out->offload_cond);
3561
3562 return 0;
3563}
3564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565static int stop_output_stream(struct stream_out *out)
3566{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303567 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568 struct audio_usecase *uc_info;
3569 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003570 bool has_voip_usecase =
3571 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572
Eric Laurent994a6932013-07-17 11:51:42 -07003573 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003574 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575 uc_info = get_usecase_from_list(adev, out->usecase);
3576 if (uc_info == NULL) {
3577 ALOGE("%s: Could not find the usecase (%d) in the list",
3578 __func__, out->usecase);
3579 return -EINVAL;
3580 }
3581
Derek Chenea197282019-01-07 17:35:01 -08003582 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3583 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003584
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003585 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303586 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003587 if (adev->visualizer_stop_output != NULL)
3588 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003589
3590 audio_extn_dts_remove_state_notifier_node(out->usecase);
3591
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003592 if (adev->offload_effects_stop_output != NULL)
3593 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003594 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3595 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3596 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003597 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003598
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003599 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3600 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003601 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003602 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003603
Eric Laurent150dbfe2013-02-27 14:31:02 -08003604 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003605 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003606
3607 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003608 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609
Aalique Grahame22e49102018-12-18 14:23:57 -08003610 audio_extn_extspk_update(adev->extspk);
3611
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003612 if (is_offload_usecase(out->usecase)) {
3613 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3614 adev->dsp_bit_width_enforce_mode,
3615 false);
3616 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003617 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003618 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3619 false);
3620
3621 if (ret != 0)
3622 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3623 /* default service interval was successfully updated,
3624 reopen USB backend with new service interval */
3625 ret = 0;
3626 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003627
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003628 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303629 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003630 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303631 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003632 ALOGV("Disable passthrough , reset mixer to pcm");
3633 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003634#ifdef AUDIO_GKI_ENABLED
3635 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3636 out->compr_config.codec->reserved[0] = 0;
3637#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003638 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003639#endif
Mingming Yin21854652016-04-13 11:54:02 -07003640 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003641 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3642 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003643
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303644 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003645 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303646 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303647
Manish Dewangan21a850a2017-08-14 12:03:55 +05303648 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003649 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3650 if (ret < 0)
3651 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3652 }
3653
juyuchen2d415992018-11-16 14:15:16 +08003654 /* 1) media + voip output routing to handset must route media back to
3655 speaker when voip stops.
3656 2) trigger voip input to reroute when voip output changes to
3657 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003658 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003659 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003660 struct listnode *node;
3661 struct audio_usecase *usecase;
3662 list_for_each(node, &adev->usecase_list) {
3663 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003664 if ((usecase->type == PCM_CAPTURE &&
3665 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3666 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003667 continue;
3668
3669 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3670 __func__, usecase->id, use_case_table[usecase->id],
3671 out->usecase, use_case_table[out->usecase]);
3672 select_devices(adev, usecase->id);
3673 }
3674 }
3675
Garmond Leung5fd0b552018-04-17 11:56:12 -07003676 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003677 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678 return ret;
3679}
3680
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003681struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3682 unsigned int flags, unsigned int pcm_open_retry_count,
3683 struct pcm_config *config)
3684{
3685 struct pcm* pcm = NULL;
3686
3687 while (1) {
3688 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3689 if (pcm == NULL || !pcm_is_ready(pcm)) {
3690 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3691 if (pcm != NULL) {
3692 pcm_close(pcm);
3693 pcm = NULL;
3694 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003695 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003696 return NULL;
3697
Weiyin Jiang72197252019-10-09 11:49:32 +08003698 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003699 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3700 continue;
3701 }
3702 break;
3703 }
3704
3705 if (pcm_is_ready(pcm)) {
3706 int ret = pcm_prepare(pcm);
3707 if (ret < 0) {
3708 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3709 pcm_close(pcm);
3710 pcm = NULL;
3711 }
3712 }
3713
3714 return pcm;
3715}
3716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717int start_output_stream(struct stream_out *out)
3718{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 struct audio_usecase *uc_info;
3721 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003722 char mixer_ctl_name[128];
3723 struct mixer_ctl *ctl = NULL;
3724 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303725 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003726 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727
Haynes Mathew George380745d2017-10-04 15:27:45 -07003728 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003729 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3730 ret = -EINVAL;
3731 goto error_config;
3732 }
3733
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003734 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303735 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003736 get_device_types(&out->device_list), is_haptic_usecase);
3737
3738 bool is_speaker_active = compare_device_type(&out->device_list,
3739 AUDIO_DEVICE_OUT_SPEAKER);
3740 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3741 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303742
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303743 if (CARD_STATUS_OFFLINE == out->card_status ||
3744 CARD_STATUS_OFFLINE == adev->card_status) {
3745 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303746 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003747 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303748 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303749
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003750 //Update incall music usecase to reflect correct voice session
3751 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3752 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3753 if (ret != 0) {
3754 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3755 __func__, ret);
3756 goto error_config;
3757 }
3758 }
3759
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003760 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003761 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003762 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303763 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303764 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303765 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3766 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3767 ret = -EAGAIN;
3768 goto error_config;
3769 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303770 }
3771 }
3772 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003773 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303774 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003775 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303776 //combo usecase just by pass a2dp
3777 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003778 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303779 } else {
3780 ALOGE("%s: SCO profile is not ready, return error", __func__);
3781 ret = -EAGAIN;
3782 goto error_config;
3783 }
3784 }
3785 }
3786
Eric Laurentb23d5282013-05-14 15:27:20 -07003787 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788 if (out->pcm_device_id < 0) {
3789 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3790 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003791 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003792 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 }
3794
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003795 if (is_haptic_usecase) {
3796 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3797 if (adev->haptic_pcm_device_id < 0) {
3798 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3799 __func__, adev->haptic_pcm_device_id, out->usecase);
3800 ret = -EINVAL;
3801 goto error_config;
3802 }
3803 }
3804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003806
3807 if (!uc_info) {
3808 ret = -ENOMEM;
3809 goto error_config;
3810 }
3811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812 uc_info->id = out->usecase;
3813 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003814 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003815 list_init(&uc_info->device_list);
3816 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003817 uc_info->in_snd_device = SND_DEVICE_NONE;
3818 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003819
3820 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003821 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003822 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3823 /* USB backend is not reopened immediately.
3824 This is eventually done as part of select_devices */
3825 }
3826
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003827 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828
Wei Wangf7ca6c92017-11-21 14:51:20 -08003829 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303830 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3831 adev->perf_lock_opts,
3832 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303833
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003834 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303835 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303836 if (audio_extn_passthru_is_enabled() &&
3837 audio_extn_passthru_is_passthrough_stream(out)) {
3838 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303839 }
3840 }
3841
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003842 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003843 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303844 if (!a2dp_combo) {
3845 check_a2dp_restore_l(adev, out, false);
3846 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003847 struct listnode dev;
3848 list_init(&dev);
3849 assign_devices(&dev, &out->device_list);
3850 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3851 reassign_device_list(&out->device_list,
3852 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003853 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003854 reassign_device_list(&out->device_list,
3855 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303856 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003857 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303858 }
3859 } else {
3860 select_devices(adev, out->usecase);
3861 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003862
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003863 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3864 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003865 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003866 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003867
Derek Chenea197282019-01-07 17:35:01 -08003868 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3869 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003870
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003871 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3872 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003873
3874 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003875 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003876 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3877 ALOGE("%s: pcm stream not ready", __func__);
3878 goto error_open;
3879 }
3880 ret = pcm_start(out->pcm);
3881 if (ret < 0) {
3882 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3883 goto error_open;
3884 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003885 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003886 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003887 unsigned int flags = PCM_OUT;
3888 unsigned int pcm_open_retry_count = 0;
3889 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3890 flags |= PCM_MMAP | PCM_NOIRQ;
3891 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003892 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003893 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003894 } else
3895 flags |= PCM_MONOTONIC;
3896
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003897 if ((adev->vr_audio_mode_enabled) &&
3898 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3899 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3900 "PCM_Dev %d Topology", out->pcm_device_id);
3901 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3902 if (!ctl) {
3903 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3904 __func__, mixer_ctl_name);
3905 } else {
3906 //if success use ULLPP
3907 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3908 __func__, mixer_ctl_name, out->pcm_device_id);
3909 //There is a still a possibility that some sessions
3910 // that request for FAST|RAW when 3D audio is active
3911 //can go through ULLPP. Ideally we expects apps to
3912 //listen to audio focus and stop concurrent playback
3913 //Also, we will look for mode flag (voice_in_communication)
3914 //before enabling the realtime flag.
3915 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3916 }
3917 }
3918
Surendar Karka91fa3682018-07-02 18:12:12 +05303919 if (out->realtime)
3920 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3921 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3922
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003923 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3924 flags, pcm_open_retry_count,
3925 &(out->config));
3926 if (out->pcm == NULL) {
3927 ret = -EIO;
3928 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003929 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003930
3931 if (is_haptic_usecase) {
3932 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3933 adev->haptic_pcm_device_id,
3934 flags, pcm_open_retry_count,
3935 &(adev->haptics_config));
3936 // failure to open haptics pcm shouldnt stop audio,
3937 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003938
3939 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3940 ALOGD("%s: enable haptic audio synchronization", __func__);
3941 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3942 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003943 }
3944
Surendar Karka91fa3682018-07-02 18:12:12 +05303945 if (!out->realtime)
3946 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303947 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003948
Zhou Song2b8f28f2017-09-11 10:51:38 +08003949 // apply volume for voip playback after path is set up
3950 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3951 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303952 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3953 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303954 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3955 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003956 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3957 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303958 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003959 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08003960 /*
3961 * set custom channel map if:
3962 * 1. neither mono nor stereo clips i.e. channels > 2 OR
3963 * 2. custom channel map has been set by client
3964 * else default channel map of FC/FR/FL can always be set to DSP
3965 */
3966 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
3967 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3968 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003969 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3970 adev->dsp_bit_width_enforce_mode,
3971 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003972 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003973 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003974 out->compr = compress_open(adev->snd_card,
3975 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003976 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003977 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303978 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303979 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3980 adev->card_status = CARD_STATUS_OFFLINE;
3981 out->card_status = CARD_STATUS_OFFLINE;
3982 ret = -EIO;
3983 goto error_open;
3984 }
3985
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003986 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003987 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003988 compress_close(out->compr);
3989 out->compr = NULL;
3990 ret = -EIO;
3991 goto error_open;
3992 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303993 /* compress_open sends params of the track, so reset the flag here */
3994 out->is_compr_metadata_avail = false;
3995
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003996 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003997 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003998
Fred Oh3f43e742015-03-04 18:42:34 -08003999 /* Since small bufs uses blocking writes, a write will be blocked
4000 for the default max poll time (20s) in the event of an SSR.
4001 Reduce the poll time to observe and deal with SSR faster.
4002 */
Ashish Jain5106d362016-05-11 19:23:33 +05304003 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004004 compress_set_max_poll_wait(out->compr, 1000);
4005 }
4006
Manish Dewangan69426c82017-01-30 17:35:36 +05304007 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304008 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304009
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004010 audio_extn_dts_create_state_notifier_node(out->usecase);
4011 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4012 popcount(out->channel_mask),
4013 out->playback_started);
4014
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004015#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304016 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004017 audio_extn_dolby_send_ddp_endp_params(adev);
4018#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304019 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4020 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004021 if (adev->visualizer_start_output != NULL)
4022 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4023 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304024 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004025 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004026 }
Derek Chenf13dd492018-11-13 14:53:51 -08004027
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004028 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004029 /* Update cached volume from media to offload/direct stream */
4030 struct listnode *node = NULL;
4031 list_for_each(node, &adev->active_outputs_list) {
4032 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4033 streams_output_ctxt_t,
4034 list);
4035 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4036 out->volume_l = out_ctxt->output->volume_l;
4037 out->volume_r = out_ctxt->output->volume_r;
4038 }
4039 }
4040 out_set_compr_volume(&out->stream,
4041 out->volume_l, out->volume_r);
4042 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004043 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004044
4045 if (ret == 0) {
4046 register_out_stream(out);
4047 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004048 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4049 ALOGE("%s: pcm stream not ready", __func__);
4050 goto error_open;
4051 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004052 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004053 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004054 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004055 if (ret < 0)
4056 goto error_open;
4057 }
4058 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004059 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304060 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004061 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004062
vivek mehtad15d2bf2019-05-17 13:35:10 -07004063 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4064 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4065 audio_low_latency_hint_start();
4066 }
4067
Manish Dewangan21a850a2017-08-14 12:03:55 +05304068 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004069 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004070 if (ret < 0)
4071 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4072 }
4073
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004074 // consider a scenario where on pause lower layers are tear down.
4075 // so on resume, swap mixer control need to be sent only when
4076 // backend is active, hence rather than sending from enable device
4077 // sending it from start of streamtream
4078
4079 platform_set_swap_channels(adev, true);
4080
Haynes Mathew George380745d2017-10-04 15:27:45 -07004081 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304082 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004083 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004084error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004085 if (adev->haptic_pcm) {
4086 pcm_close(adev->haptic_pcm);
4087 adev->haptic_pcm = NULL;
4088 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004089 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304090 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004092error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304093 /*
4094 * sleep 50ms to allow sufficient time for kernel
4095 * drivers to recover incases like SSR.
4096 */
4097 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004098error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004099 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304100 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004101 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004102}
4103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004104static int check_input_parameters(uint32_t sample_rate,
4105 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004106 int channel_count,
4107 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004109 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004110
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304111 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4112 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4113 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004114 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004115 !audio_extn_compr_cap_format_supported(format) &&
4116 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004117 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004118
Aalique Grahame22e49102018-12-18 14:23:57 -08004119 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4120 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4121 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4122 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4123 return -EINVAL;
4124 }
4125
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004126 switch (channel_count) {
4127 case 1:
4128 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304129 case 3:
4130 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004131 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004132 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304133 case 10:
4134 case 12:
4135 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004136 break;
4137 default:
4138 ret = -EINVAL;
4139 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140
4141 switch (sample_rate) {
4142 case 8000:
4143 case 11025:
4144 case 12000:
4145 case 16000:
4146 case 22050:
4147 case 24000:
4148 case 32000:
4149 case 44100:
4150 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004151 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304152 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004153 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304154 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004155 break;
4156 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004157 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004158 }
4159
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004160 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161}
4162
Naresh Tanniru04f71882018-06-26 17:46:22 +05304163
4164/** Add a value in a list if not already present.
4165 * @return true if value was successfully inserted or already present,
4166 * false if the list is full and does not contain the value.
4167 */
4168static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4169 for (size_t i = 0; i < list_length; i++) {
4170 if (list[i] == value) return true; // value is already present
4171 if (list[i] == 0) { // no values in this slot
4172 list[i] = value;
4173 return true; // value inserted
4174 }
4175 }
4176 return false; // could not insert value
4177}
4178
4179/** Add channel_mask in supported_channel_masks if not already present.
4180 * @return true if channel_mask was successfully inserted or already present,
4181 * false if supported_channel_masks is full and does not contain channel_mask.
4182 */
4183static void register_channel_mask(audio_channel_mask_t channel_mask,
4184 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4185 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4186 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4187}
4188
4189/** Add format in supported_formats if not already present.
4190 * @return true if format was successfully inserted or already present,
4191 * false if supported_formats is full and does not contain format.
4192 */
4193static void register_format(audio_format_t format,
4194 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4195 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4196 "%s: stream can not declare supporting its format %x", __func__, format);
4197}
4198/** Add sample_rate in supported_sample_rates if not already present.
4199 * @return true if sample_rate was successfully inserted or already present,
4200 * false if supported_sample_rates is full and does not contain sample_rate.
4201 */
4202static void register_sample_rate(uint32_t sample_rate,
4203 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4204 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4205 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4206}
4207
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004208static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4209{
4210 uint32_t high = num1, low = num2, temp = 0;
4211
4212 if (!num1 || !num2)
4213 return 0;
4214
4215 if (num1 < num2) {
4216 high = num2;
4217 low = num1;
4218 }
4219
4220 while (low != 0) {
4221 temp = low;
4222 low = high % low;
4223 high = temp;
4224 }
4225 return (num1 * num2)/high;
4226}
4227
4228static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4229{
4230 uint32_t remainder = 0;
4231
4232 if (!multiplier)
4233 return num;
4234
4235 remainder = num % multiplier;
4236 if (remainder)
4237 num += (multiplier - remainder);
4238
4239 return num;
4240}
4241
Aalique Grahame22e49102018-12-18 14:23:57 -08004242static size_t get_stream_buffer_size(size_t duration_ms,
4243 uint32_t sample_rate,
4244 audio_format_t format,
4245 int channel_count,
4246 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247{
4248 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004249 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004250
Aalique Grahame22e49102018-12-18 14:23:57 -08004251 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004252 if (is_low_latency)
4253 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304254
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004255 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004256 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257
Ralf Herzbd08d632018-09-28 15:50:49 +02004258 /* make sure the size is multiple of 32 bytes and additionally multiple of
4259 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004260 * At 48 kHz mono 16-bit PCM:
4261 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4262 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004263 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004264 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004265 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004266
4267 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004268}
4269
Aalique Grahame22e49102018-12-18 14:23:57 -08004270static size_t get_input_buffer_size(uint32_t sample_rate,
4271 audio_format_t format,
4272 int channel_count,
4273 bool is_low_latency)
4274{
4275 /* Don't know if USB HIFI in this context so use true to be conservative */
4276 if (check_input_parameters(sample_rate, format, channel_count,
4277 true /*is_usb_hifi */) != 0)
4278 return 0;
4279
4280 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4281 sample_rate,
4282 format,
4283 channel_count,
4284 is_low_latency);
4285}
4286
Derek Chenf6318be2017-06-12 17:16:24 -04004287size_t get_output_period_size(uint32_t sample_rate,
4288 audio_format_t format,
4289 int channel_count,
4290 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304291{
4292 size_t size = 0;
4293 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4294
4295 if ((duration == 0) || (sample_rate == 0) ||
4296 (bytes_per_sample == 0) || (channel_count == 0)) {
4297 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4298 bytes_per_sample, channel_count);
4299 return -EINVAL;
4300 }
4301
4302 size = (sample_rate *
4303 duration *
4304 bytes_per_sample *
4305 channel_count) / 1000;
4306 /*
4307 * To have same PCM samples for all channels, the buffer size requires to
4308 * be multiple of (number of channels * bytes per sample)
4309 * For writes to succeed, the buffer must be written at address which is multiple of 32
4310 */
4311 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4312
4313 return (size/(channel_count * bytes_per_sample));
4314}
4315
Zhou Song48453a02018-01-10 17:50:59 +08004316static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304317{
4318 uint64_t actual_frames_rendered = 0;
4319 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4320
4321 /* This adjustment accounts for buffering after app processor.
4322 * It is based on estimated DSP latency per use case, rather than exact.
4323 */
Robert Lee58215542019-07-15 20:55:12 +08004324 pthread_mutex_lock(&adev->lock);
4325 int64_t platform_latency = platform_render_latency(out->dev, out->usecase) *
Ashish Jain5106d362016-05-11 19:23:33 +05304326 out->sample_rate / 1000000LL;
Robert Lee58215542019-07-15 20:55:12 +08004327 pthread_mutex_unlock(&adev->lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304328
Zhou Song48453a02018-01-10 17:50:59 +08004329 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304330 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4331 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4332 * hence only estimate.
4333 */
George Gao62ebc722019-07-29 16:29:44 -07004334 uint64_t signed_frames = 0;
4335 if (out->written >= kernel_buffer_size)
4336 signed_frames = out->written - kernel_buffer_size;
Ashish Jain5106d362016-05-11 19:23:33 +05304337
George Gao62ebc722019-07-29 16:29:44 -07004338 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask));
4339 if (signed_frames >= platform_latency)
4340 signed_frames = signed_frames - platform_latency;
Ashish Jain5106d362016-05-11 19:23:33 +05304341
Zhou Song48453a02018-01-10 17:50:59 +08004342 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304343 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004344 if (timestamp != NULL )
4345 *timestamp = out->writeAt;
4346 } else if (timestamp != NULL) {
4347 clock_gettime(CLOCK_MONOTONIC, timestamp);
4348 }
4349 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304350
4351 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
George Gao62ebc722019-07-29 16:29:44 -07004352 "bytes/sample %zu channel count %d", __func__, signed_frames,
Ashish Jain5106d362016-05-11 19:23:33 +05304353 (long long int)out->written, (int)kernel_buffer_size,
4354 audio_bytes_per_sample(out->compr_config.codec->format),
4355 popcount(out->channel_mask));
4356
4357 return actual_frames_rendered;
4358}
4359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4361{
4362 struct stream_out *out = (struct stream_out *)stream;
4363
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004364 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004365}
4366
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004367static int out_set_sample_rate(struct audio_stream *stream __unused,
4368 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004369{
4370 return -ENOSYS;
4371}
4372
4373static size_t out_get_buffer_size(const struct audio_stream *stream)
4374{
4375 struct stream_out *out = (struct stream_out *)stream;
4376
Varun Balaraje49253e2017-07-06 19:48:56 +05304377 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304378 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304379 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304380 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4381 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4382 else
4383 return out->compr_config.fragment_size;
4384 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004385 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304386 else if (is_offload_usecase(out->usecase) &&
4387 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304388 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004389
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004390 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004391 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392}
4393
4394static uint32_t out_get_channels(const struct audio_stream *stream)
4395{
4396 struct stream_out *out = (struct stream_out *)stream;
4397
4398 return out->channel_mask;
4399}
4400
4401static audio_format_t out_get_format(const struct audio_stream *stream)
4402{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004403 struct stream_out *out = (struct stream_out *)stream;
4404
4405 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406}
4407
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004408static int out_set_format(struct audio_stream *stream __unused,
4409 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004410{
4411 return -ENOSYS;
4412}
4413
4414static int out_standby(struct audio_stream *stream)
4415{
4416 struct stream_out *out = (struct stream_out *)stream;
4417 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004418 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004419
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304420 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4421 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004423 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004424 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004425 if (adev->adm_deregister_stream)
4426 adev->adm_deregister_stream(adev->adm_data, out->handle);
4427
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004428 if (is_offload_usecase(out->usecase))
4429 stop_compressed_output_l(out);
4430
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004431 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004433 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4434 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304435 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004436 pthread_mutex_unlock(&adev->lock);
4437 pthread_mutex_unlock(&out->lock);
4438 ALOGD("VOIP output entered standby");
4439 return 0;
4440 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004441 if (out->pcm) {
4442 pcm_close(out->pcm);
4443 out->pcm = NULL;
4444 }
Meng Wanga09da002020-04-20 12:56:04 +08004445 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4446 if (adev->haptic_pcm) {
4447 pcm_close(adev->haptic_pcm);
4448 adev->haptic_pcm = NULL;
4449 }
4450
4451 if (adev->haptic_buffer != NULL) {
4452 free(adev->haptic_buffer);
4453 adev->haptic_buffer = NULL;
4454 adev->haptic_buffer_size = 0;
4455 }
4456 adev->haptic_pcm_device_id = 0;
4457 }
4458
Haynes Mathew George16081042017-05-31 17:16:49 -07004459 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4460 do_stop = out->playback_started;
4461 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004462
4463 if (out->mmap_shared_memory_fd >= 0) {
4464 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4465 __func__, out->mmap_shared_memory_fd);
4466 close(out->mmap_shared_memory_fd);
4467 out->mmap_shared_memory_fd = -1;
4468 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004469 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004470 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004471 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304472 out->send_next_track_params = false;
4473 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004474 out->gapless_mdata.encoder_delay = 0;
4475 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004476 if (out->compr != NULL) {
4477 compress_close(out->compr);
4478 out->compr = NULL;
4479 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004480 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004481 if (do_stop) {
4482 stop_output_stream(out);
4483 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304484 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004485 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004486 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487 }
4488 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304489 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004490 return 0;
4491}
4492
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304493static int out_on_error(struct audio_stream *stream)
4494{
4495 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004496 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304497
4498 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004499 // always send CMD_ERROR for offload streams, this
4500 // is needed e.g. when SSR happens within compress_open
4501 // since the stream is active, offload_callback_thread is also active.
4502 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4503 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004504 }
4505 pthread_mutex_unlock(&out->lock);
4506
4507 status = out_standby(&out->stream.common);
4508
4509 lock_output_stream(out);
4510 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004511 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304512 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304513
4514 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4515 ALOGD("Setting previous card status if offline");
4516 out->prev_card_status_offline = true;
4517 }
4518
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304519 pthread_mutex_unlock(&out->lock);
4520
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004521 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304522}
4523
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304524/*
4525 *standby implementation without locks, assumes that the callee already
4526 *has taken adev and out lock.
4527 */
4528int out_standby_l(struct audio_stream *stream)
4529{
4530 struct stream_out *out = (struct stream_out *)stream;
4531 struct audio_device *adev = out->dev;
4532
4533 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4534 stream, out->usecase, use_case_table[out->usecase]);
4535
4536 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004537 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304538 if (adev->adm_deregister_stream)
4539 adev->adm_deregister_stream(adev->adm_data, out->handle);
4540
4541 if (is_offload_usecase(out->usecase))
4542 stop_compressed_output_l(out);
4543
4544 out->standby = true;
4545 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4546 voice_extn_compress_voip_close_output_stream(stream);
4547 out->started = 0;
4548 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004549 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304550 return 0;
4551 } else if (!is_offload_usecase(out->usecase)) {
4552 if (out->pcm) {
4553 pcm_close(out->pcm);
4554 out->pcm = NULL;
4555 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004556 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4557 if (adev->haptic_pcm) {
4558 pcm_close(adev->haptic_pcm);
4559 adev->haptic_pcm = NULL;
4560 }
4561
4562 if (adev->haptic_buffer != NULL) {
4563 free(adev->haptic_buffer);
4564 adev->haptic_buffer = NULL;
4565 adev->haptic_buffer_size = 0;
4566 }
4567 adev->haptic_pcm_device_id = 0;
4568 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304569 } else {
4570 ALOGD("copl(%p):standby", out);
4571 out->send_next_track_params = false;
4572 out->is_compr_metadata_avail = false;
4573 out->gapless_mdata.encoder_delay = 0;
4574 out->gapless_mdata.encoder_padding = 0;
4575 if (out->compr != NULL) {
4576 compress_close(out->compr);
4577 out->compr = NULL;
4578 }
4579 }
4580 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004581 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304582 }
4583 ALOGD("%s: exit", __func__);
4584 return 0;
4585}
4586
Aalique Grahame22e49102018-12-18 14:23:57 -08004587static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588{
Aalique Grahame22e49102018-12-18 14:23:57 -08004589 struct stream_out *out = (struct stream_out *)stream;
4590
4591 // We try to get the lock for consistency,
4592 // but it isn't necessary for these variables.
4593 // If we're not in standby, we may be blocked on a write.
4594 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4595 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4596 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4597
Andy Hunga1f48fa2019-07-01 18:14:53 -07004598 char buffer[256]; // for statistics formatting
4599 if (!is_offload_usecase(out->usecase)) {
4600 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4601 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4602 }
4603
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004604 if (out->start_latency_ms.n > 0) {
4605 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4606 dprintf(fd, " Start latency ms: %s\n", buffer);
4607 }
4608
Aalique Grahame22e49102018-12-18 14:23:57 -08004609 if (locked) {
4610 pthread_mutex_unlock(&out->lock);
4611 }
4612
4613 // dump error info
4614 (void)error_log_dump(
4615 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617 return 0;
4618}
4619
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004620static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4621{
4622 int ret = 0;
4623 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004624
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004625 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004626 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004627 return -EINVAL;
4628 }
4629
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304630 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004631
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004632 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4633 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304634 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004635 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004636 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4637 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304638 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004639 }
4640
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004641 ALOGV("%s new encoder delay %u and padding %u", __func__,
4642 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4643
4644 return 0;
4645}
4646
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004647static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4648{
4649 return out == adev->primary_output || out == adev->voice_tx_output;
4650}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004651
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304652// note: this call is safe only if the stream_cb is
4653// removed first in close_output_stream (as is done now).
4654static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4655{
4656 if (!stream || !parms)
4657 return;
4658
4659 struct stream_out *out = (struct stream_out *)stream;
4660 struct audio_device *adev = out->dev;
4661
4662 card_status_t status;
4663 int card;
4664 if (parse_snd_card_status(parms, &card, &status) < 0)
4665 return;
4666
4667 pthread_mutex_lock(&adev->lock);
4668 bool valid_cb = (card == adev->snd_card);
4669 pthread_mutex_unlock(&adev->lock);
4670
4671 if (!valid_cb)
4672 return;
4673
4674 lock_output_stream(out);
4675 if (out->card_status != status)
4676 out->card_status = status;
4677 pthread_mutex_unlock(&out->lock);
4678
4679 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4680 use_case_table[out->usecase],
4681 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4682
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304683 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304684 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304685 if (voice_is_call_state_active(adev) &&
4686 out == adev->primary_output) {
4687 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4688 pthread_mutex_lock(&adev->lock);
4689 voice_stop_call(adev);
4690 adev->mode = AUDIO_MODE_NORMAL;
4691 pthread_mutex_unlock(&adev->lock);
4692 }
4693 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304694 return;
4695}
4696
Kevin Rocardfce19002017-08-07 19:21:36 -07004697static int get_alive_usb_card(struct str_parms* parms) {
4698 int card;
4699 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4700 !audio_extn_usb_alive(card)) {
4701 return card;
4702 }
4703 return -ENODEV;
4704}
4705
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004706int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004707 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004708{
4709 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004710 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004711 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004712 bool bypass_a2dp = false;
4713 bool reconfig = false;
4714 unsigned long service_interval = 0;
4715
4716 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004717 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4718
4719 list_init(&new_devices);
4720 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004721
4722 lock_output_stream(out);
4723 pthread_mutex_lock(&adev->lock);
4724
4725 /*
4726 * When HDMI cable is unplugged the music playback is paused and
4727 * the policy manager sends routing=0. But the audioflinger continues
4728 * to write data until standby time (3sec). As the HDMI core is
4729 * turned off, the write gets blocked.
4730 * Avoid this by routing audio to speaker until standby.
4731 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004732 if (is_single_device_type_equal(&out->device_list,
4733 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004734 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004735 !audio_extn_passthru_is_passthrough_stream(out) &&
4736 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004737 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004738 }
4739 /*
4740 * When A2DP is disconnected the
4741 * music playback is paused and the policy manager sends routing=0
4742 * But the audioflinger continues to write data until standby time
4743 * (3sec). As BT is turned off, the write gets blocked.
4744 * Avoid this by routing audio to speaker until standby.
4745 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004746 if (is_a2dp_out_device_type(&out->device_list) &&
4747 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004748 !audio_extn_a2dp_source_is_ready() &&
4749 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004750 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004751 }
4752 /*
4753 * When USB headset is disconnected the music platback paused
4754 * and the policy manager send routing=0. But if the USB is connected
4755 * back before the standby time, AFE is not closed and opened
4756 * when USB is connected back. So routing to speker will guarantee
4757 * AFE reconfiguration and AFE will be opend once USB is connected again
4758 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004759 if (is_usb_out_device_type(&out->device_list) &&
4760 list_empty(&new_devices) &&
4761 !audio_extn_usb_connected(NULL)) {
4762 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4763 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004764 /* To avoid a2dp to sco overlapping / BT device improper state
4765 * check with BT lib about a2dp streaming support before routing
4766 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004767 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004768 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004769 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4770 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004771 //combo usecase just by pass a2dp
4772 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4773 bypass_a2dp = true;
4774 } else {
4775 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4776 /* update device to a2dp and don't route as BT returned error
4777 * However it is still possible a2dp routing called because
4778 * of current active device disconnection (like wired headset)
4779 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004780 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004781 pthread_mutex_unlock(&adev->lock);
4782 pthread_mutex_unlock(&out->lock);
4783 goto error;
4784 }
4785 }
4786 }
4787
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004788 // Workaround: If routing to an non existing usb device, fail gracefully
4789 // The routing request will otherwise block during 10 second
4790 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004791 if (is_usb_out_device_type(&new_devices)) {
4792 struct str_parms *parms =
4793 str_parms_create_str(get_usb_device_address(&new_devices));
4794 if (!parms)
4795 goto error;
4796 if ((card = get_alive_usb_card(parms)) >= 0) {
4797 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4798 pthread_mutex_unlock(&adev->lock);
4799 pthread_mutex_unlock(&out->lock);
4800 str_parms_destroy(parms);
4801 ret = -ENOSYS;
4802 goto error;
4803 }
4804 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004805 }
4806
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004807 // Workaround: If routing to an non existing hdmi device, fail gracefully
4808 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4809 (platform_get_edid_info_v2(adev->platform,
4810 out->extconn.cs.controller,
4811 out->extconn.cs.stream) != 0)) {
4812 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4813 pthread_mutex_unlock(&adev->lock);
4814 pthread_mutex_unlock(&out->lock);
4815 ret = -ENOSYS;
4816 goto error;
4817 }
4818
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004819 /*
4820 * select_devices() call below switches all the usecases on the same
4821 * backend to the new device. Refer to check_usecases_codec_backend() in
4822 * the select_devices(). But how do we undo this?
4823 *
4824 * For example, music playback is active on headset (deep-buffer usecase)
4825 * and if we go to ringtones and select a ringtone, low-latency usecase
4826 * will be started on headset+speaker. As we can't enable headset+speaker
4827 * and headset devices at the same time, select_devices() switches the music
4828 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4829 * So when the ringtone playback is completed, how do we undo the same?
4830 *
4831 * We are relying on the out_set_parameters() call on deep-buffer output,
4832 * once the ringtone playback is ended.
4833 * NOTE: We should not check if the current devices are same as new devices.
4834 * Because select_devices() must be called to switch back the music
4835 * playback to headset.
4836 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004837 if (!list_empty(&new_devices)) {
4838 bool same_dev = compare_devices(&out->device_list, &new_devices);
4839 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004840
4841 if (output_drives_call(adev, out)) {
4842 if (!voice_is_call_state_active(adev)) {
4843 if (adev->mode == AUDIO_MODE_IN_CALL) {
4844 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004845 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004846 service_interval =
4847 audio_extn_usb_find_service_interval(true, true /*playback*/);
4848 audio_extn_usb_set_service_interval(true /*playback*/,
4849 service_interval,
4850 &reconfig);
4851 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4852 }
4853 ret = voice_start_call(adev);
4854 }
4855 } else {
4856 adev->current_call_output = out;
4857 voice_update_devices_for_all_voice_usecases(adev);
4858 }
4859 }
4860
4861 if (!out->standby) {
4862 if (!same_dev) {
4863 ALOGV("update routing change");
4864 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4865 adev->perf_lock_opts,
4866 adev->perf_lock_opts_size);
4867 if (adev->adm_on_routing_change)
4868 adev->adm_on_routing_change(adev->adm_data,
4869 out->handle);
4870 }
4871 if (!bypass_a2dp) {
4872 select_devices(adev, out->usecase);
4873 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004874 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4875 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004876 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004877 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004878 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004879 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004880 }
4881
4882 if (!same_dev) {
4883 // on device switch force swap, lower functions will make sure
4884 // to check if swap is allowed or not.
4885 platform_set_swap_channels(adev, true);
4886 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4887 }
4888 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4889 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004890 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004891 pthread_mutex_lock(&out->compr_mute_lock);
4892 out->a2dp_compress_mute = false;
4893 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4894 pthread_mutex_unlock(&out->compr_mute_lock);
4895 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4896 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4897 }
4898 }
4899 }
4900
4901 pthread_mutex_unlock(&adev->lock);
4902 pthread_mutex_unlock(&out->lock);
4903
4904 /*handles device and call state changes*/
4905 audio_extn_extspk_update(adev->extspk);
4906
4907error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004908 ALOGV("%s: exit: code(%d)", __func__, ret);
4909 return ret;
4910}
4911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004912static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4913{
4914 struct stream_out *out = (struct stream_out *)stream;
4915 struct audio_device *adev = out->dev;
4916 struct str_parms *parms;
4917 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004918 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004919 int ext_controller = -1;
4920 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004921
sangwoobc677242013-08-08 16:53:43 +09004922 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004923 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004924 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304925 if (!parms)
4926 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004927
4928 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4929 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08004930 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004931 out->extconn.cs.controller = ext_controller;
4932 out->extconn.cs.stream = ext_stream;
4933 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4934 use_case_table[out->usecase], out->extconn.cs.controller,
4935 out->extconn.cs.stream);
4936 }
4937
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004938 if (out == adev->primary_output) {
4939 pthread_mutex_lock(&adev->lock);
4940 audio_extn_set_parameters(adev, parms);
4941 pthread_mutex_unlock(&adev->lock);
4942 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004943 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004944 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004945 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004946
4947 audio_extn_dts_create_state_notifier_node(out->usecase);
4948 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4949 popcount(out->channel_mask),
4950 out->playback_started);
4951
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004952 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004953 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004954
Surendar Karkaf51b5842018-04-26 11:28:38 +05304955 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4956 sizeof(value));
4957 if (err >= 0) {
4958 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4959 audio_extn_send_dual_mono_mixing_coefficients(out);
4960 }
4961
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304962 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4963 if (err >= 0) {
4964 strlcpy(out->profile, value, sizeof(out->profile));
4965 ALOGV("updating stream profile with value '%s'", out->profile);
4966 lock_output_stream(out);
4967 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4968 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004969 &out->device_list, out->flags,
4970 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304971 out->sample_rate, out->bit_width,
4972 out->channel_mask, out->profile,
4973 &out->app_type_cfg);
4974 pthread_mutex_unlock(&out->lock);
4975 }
4976
Alexy Joseph98988832017-01-13 14:56:59 -08004977 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004978 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4979 // and vendor.audio.hal.output.suspend.supported is set to true
4980 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004981 //check suspend parameter only for low latency and if the property
4982 //is enabled
4983 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4984 ALOGI("%s: got suspend_playback %s", __func__, value);
4985 lock_output_stream(out);
4986 if (!strncmp(value, "false", 5)) {
4987 //suspend_playback=false is supposed to set QOS value back to 75%
4988 //the mixer control sent with value Enable will achieve that
4989 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4990 } else if (!strncmp (value, "true", 4)) {
4991 //suspend_playback=true is supposed to remove QOS value
4992 //resetting the mixer control will set the default value
4993 //for the mixer control which is Disable and this removes the QOS vote
4994 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4995 } else {
4996 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4997 " got %s", __func__, value);
4998 ret = -1;
4999 }
5000
5001 if (ret != 0) {
5002 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5003 __func__, out->pm_qos_mixer_path, ret);
5004 }
5005
5006 pthread_mutex_unlock(&out->lock);
5007 }
5008 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005009
Alexy Joseph98988832017-01-13 14:56:59 -08005010 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005011 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305012error:
Eric Laurent994a6932013-07-17 11:51:42 -07005013 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005014 return ret;
5015}
5016
Paul McLeana50b7332018-12-17 08:24:21 -07005017static int in_set_microphone_direction(const struct audio_stream_in *stream,
5018 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005019 struct stream_in *in = (struct stream_in *)stream;
5020
5021 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5022
5023 in->direction = dir;
5024
5025 if (in->standby)
5026 return 0;
5027
5028 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005029}
5030
5031static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005032 struct stream_in *in = (struct stream_in *)stream;
5033
5034 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5035
5036 if (zoom > 1.0 || zoom < -1.0)
5037 return -EINVAL;
5038
5039 in->zoom = zoom;
5040
5041 if (in->standby)
5042 return 0;
5043
5044 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005045}
5046
5047
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005048static bool stream_get_parameter_channels(struct str_parms *query,
5049 struct str_parms *reply,
5050 audio_channel_mask_t *supported_channel_masks) {
5051 int ret = -1;
5052 char value[512];
5053 bool first = true;
5054 size_t i, j;
5055
5056 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5057 ret = 0;
5058 value[0] = '\0';
5059 i = 0;
5060 while (supported_channel_masks[i] != 0) {
5061 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5062 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5063 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305064 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005065
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305066 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005067 first = false;
5068 break;
5069 }
5070 }
5071 i++;
5072 }
5073 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5074 }
5075 return ret == 0;
5076}
5077
5078static bool stream_get_parameter_formats(struct str_parms *query,
5079 struct str_parms *reply,
5080 audio_format_t *supported_formats) {
5081 int ret = -1;
5082 char value[256];
5083 size_t i, j;
5084 bool first = true;
5085
5086 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5087 ret = 0;
5088 value[0] = '\0';
5089 i = 0;
5090 while (supported_formats[i] != 0) {
5091 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5092 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5093 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305094 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005095 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305096 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005097 first = false;
5098 break;
5099 }
5100 }
5101 i++;
5102 }
5103 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5104 }
5105 return ret == 0;
5106}
5107
5108static bool stream_get_parameter_rates(struct str_parms *query,
5109 struct str_parms *reply,
5110 uint32_t *supported_sample_rates) {
5111
5112 int i;
5113 char value[256];
5114 int ret = -1;
5115 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5116 ret = 0;
5117 value[0] = '\0';
5118 i=0;
5119 int cursor = 0;
5120 while (supported_sample_rates[i]) {
5121 int avail = sizeof(value) - cursor;
5122 ret = snprintf(value + cursor, avail, "%s%d",
5123 cursor > 0 ? "|" : "",
5124 supported_sample_rates[i]);
5125 if (ret < 0 || ret >= avail) {
5126 // if cursor is at the last element of the array
5127 // overwrite with \0 is duplicate work as
5128 // snprintf already put a \0 in place.
5129 // else
5130 // we had space to write the '|' at value[cursor]
5131 // (which will be overwritten) or no space to fill
5132 // the first element (=> cursor == 0)
5133 value[cursor] = '\0';
5134 break;
5135 }
5136 cursor += ret;
5137 ++i;
5138 }
5139 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5140 value);
5141 }
5142 return ret >= 0;
5143}
5144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005145static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5146{
5147 struct stream_out *out = (struct stream_out *)stream;
5148 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005149 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005150 char value[256];
5151 struct str_parms *reply = str_parms_create();
5152 size_t i, j;
5153 int ret;
5154 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005155
5156 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005157 if (reply) {
5158 str_parms_destroy(reply);
5159 }
5160 if (query) {
5161 str_parms_destroy(query);
5162 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005163 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5164 return NULL;
5165 }
5166
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005167 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005168 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5169 if (ret >= 0) {
5170 value[0] = '\0';
5171 i = 0;
5172 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005173 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5174 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005175 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005176 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005177 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005178 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005179 first = false;
5180 break;
5181 }
5182 }
5183 i++;
5184 }
5185 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5186 str = str_parms_to_str(reply);
5187 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005188 voice_extn_out_get_parameters(out, query, reply);
5189 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005190 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005191
Alexy Joseph62142aa2015-11-16 15:10:34 -08005192
5193 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5194 if (ret >= 0) {
5195 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305196 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5197 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005198 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305199 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005200 } else {
5201 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305202 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005203 }
5204 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005205 if (str)
5206 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005207 str = str_parms_to_str(reply);
5208 }
5209
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005210 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5211 if (ret >= 0) {
5212 value[0] = '\0';
5213 i = 0;
5214 first = true;
5215 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005216 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5217 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005218 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005219 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005220 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005221 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005222 first = false;
5223 break;
5224 }
5225 }
5226 i++;
5227 }
5228 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005229 if (str)
5230 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005231 str = str_parms_to_str(reply);
5232 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005233
5234 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5235 if (ret >= 0) {
5236 value[0] = '\0';
5237 i = 0;
5238 first = true;
5239 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005240 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5241 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005242 if (!first) {
5243 strlcat(value, "|", sizeof(value));
5244 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005245 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005246 first = false;
5247 break;
5248 }
5249 }
5250 i++;
5251 }
5252 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5253 if (str)
5254 free(str);
5255 str = str_parms_to_str(reply);
5256 }
5257
Alexy Joseph98988832017-01-13 14:56:59 -08005258 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5259 //only low latency track supports suspend_resume
5260 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005261 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005262 if (str)
5263 free(str);
5264 str = str_parms_to_str(reply);
5265 }
5266
5267
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005268 str_parms_destroy(query);
5269 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005270 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005271 return str;
5272}
5273
5274static uint32_t out_get_latency(const struct audio_stream_out *stream)
5275{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005276 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005277 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005278 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005279
Alexy Josephaa54c872014-12-03 02:46:47 -08005280 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305281 lock_output_stream(out);
5282 latency = audio_extn_utils_compress_get_dsp_latency(out);
5283 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005284 } else if ((out->realtime) ||
5285 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005286 // since the buffer won't be filled up faster than realtime,
5287 // return a smaller number
5288 if (out->config.rate)
5289 period_ms = (out->af_period_multiplier * out->config.period_size *
5290 1000) / (out->config.rate);
5291 else
5292 period_ms = 0;
Robert Lee58215542019-07-15 20:55:12 +08005293 pthread_mutex_lock(&adev->lock);
5294 latency = period_ms + platform_render_latency(out->dev, out->usecase)/1000;
5295 pthread_mutex_unlock(&adev->lock);
Alexy Josephaa54c872014-12-03 02:46:47 -08005296 } else {
5297 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005298 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005299 }
5300
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005301 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005302 latency += audio_extn_a2dp_get_encoder_latency();
5303
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305304 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005305 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005306}
5307
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305308static float AmpToDb(float amplification)
5309{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305310 float db = DSD_VOLUME_MIN_DB;
5311 if (amplification > 0) {
5312 db = 20 * log10(amplification);
5313 if(db < DSD_VOLUME_MIN_DB)
5314 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305315 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305316 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305317}
5318
Arun Mirpuri5d170872019-03-26 13:21:31 -07005319static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5320 float right)
5321{
5322 struct stream_out *out = (struct stream_out *)stream;
5323 long volume = 0;
5324 char mixer_ctl_name[128] = "";
5325 struct audio_device *adev = out->dev;
5326 struct mixer_ctl *ctl = NULL;
5327 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5328 PCM_PLAYBACK);
5329
5330 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5331 "Playback %d Volume", pcm_device_id);
5332 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5333 if (!ctl) {
5334 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5335 __func__, mixer_ctl_name);
5336 return -EINVAL;
5337 }
5338 if (left != right)
5339 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5340 __func__, left, right);
5341 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5342 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5343 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5344 __func__, mixer_ctl_name, volume);
5345 return -EINVAL;
5346 }
5347 return 0;
5348}
5349
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305350static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5351 float right)
5352{
5353 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305354 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305355 char mixer_ctl_name[128];
5356 struct audio_device *adev = out->dev;
5357 struct mixer_ctl *ctl;
5358 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5359 PCM_PLAYBACK);
5360
5361 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5362 "Compress Playback %d Volume", pcm_device_id);
5363 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5364 if (!ctl) {
5365 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5366 __func__, mixer_ctl_name);
5367 return -EINVAL;
5368 }
5369 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5370 __func__, mixer_ctl_name, left, right);
5371 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5372 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5373 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5374
5375 return 0;
5376}
5377
Zhou Song2b8f28f2017-09-11 10:51:38 +08005378static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5379 float right)
5380{
5381 struct stream_out *out = (struct stream_out *)stream;
5382 char mixer_ctl_name[] = "App Type Gain";
5383 struct audio_device *adev = out->dev;
5384 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305385 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005386
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005387 if (!is_valid_volume(left, right)) {
5388 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5389 __func__, left, right);
5390 return -EINVAL;
5391 }
5392
Zhou Song2b8f28f2017-09-11 10:51:38 +08005393 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5394 if (!ctl) {
5395 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5396 __func__, mixer_ctl_name);
5397 return -EINVAL;
5398 }
5399
5400 set_values[0] = 0; //0: Rx Session 1:Tx Session
5401 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305402 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5403 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005404
5405 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5406 return 0;
5407}
5408
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305409static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5410 float right)
5411{
5412 struct stream_out *out = (struct stream_out *)stream;
5413 /* Volume control for pcm playback */
5414 if (left != right) {
5415 return -EINVAL;
5416 } else {
5417 char mixer_ctl_name[128];
5418 struct audio_device *adev = out->dev;
5419 struct mixer_ctl *ctl;
5420 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5421 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5422 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5423 if (!ctl) {
5424 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5425 return -EINVAL;
5426 }
5427
5428 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5429 int ret = mixer_ctl_set_value(ctl, 0, volume);
5430 if (ret < 0) {
5431 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5432 return -EINVAL;
5433 }
5434
5435 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5436
5437 return 0;
5438 }
5439}
5440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005441static int out_set_volume(struct audio_stream_out *stream, float left,
5442 float right)
5443{
Eric Laurenta9024de2013-04-04 09:19:12 -07005444 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005445 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305446 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005447
Arun Mirpuri5d170872019-03-26 13:21:31 -07005448 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005449 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5450 /* only take left channel into account: the API is for stereo anyway */
5451 out->muted = (left == 0.0f);
5452 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005453 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305454 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005455 /*
5456 * Set mute or umute on HDMI passthrough stream.
5457 * Only take left channel into account.
5458 * Mute is 0 and unmute 1
5459 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305460 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305461 } else if (out->format == AUDIO_FORMAT_DSD){
5462 char mixer_ctl_name[128] = "DSD Volume";
5463 struct audio_device *adev = out->dev;
5464 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5465
5466 if (!ctl) {
5467 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5468 __func__, mixer_ctl_name);
5469 return -EINVAL;
5470 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305471 volume[0] = (long)(AmpToDb(left));
5472 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305473 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5474 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005475 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005476 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005477 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5478 struct listnode *node = NULL;
5479 list_for_each(node, &adev->active_outputs_list) {
5480 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5481 streams_output_ctxt_t,
5482 list);
5483 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5484 out->volume_l = out_ctxt->output->volume_l;
5485 out->volume_r = out_ctxt->output->volume_r;
5486 }
5487 }
5488 if (!out->a2dp_compress_mute) {
5489 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5490 }
5491 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005492 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305493 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005494 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305495 if (!out->a2dp_compress_mute)
5496 ret = out_set_compr_volume(stream, left, right);
5497 out->volume_l = left;
5498 out->volume_r = right;
5499 pthread_mutex_unlock(&out->compr_mute_lock);
5500 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005501 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005502 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005503 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5504 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5505 if (!out->standby) {
5506 audio_extn_utils_send_app_type_gain(out->dev,
5507 out->app_type_cfg.app_type,
5508 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005509 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005510 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005511 out->volume_l = left;
5512 out->volume_r = right;
5513 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005514 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5515 ALOGV("%s: MMAP set volume called", __func__);
5516 if (!out->standby)
5517 ret = out_set_mmap_volume(stream, left, right);
5518 out->volume_l = left;
5519 out->volume_r = right;
5520 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305521 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305522 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5523 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305524 /* Volume control for pcm playback */
5525 if (!out->standby)
5526 ret = out_set_pcm_volume(stream, left, right);
5527 else
5528 out->apply_volume = true;
5529
5530 out->volume_l = left;
5531 out->volume_r = right;
5532 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005533 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5534 ALOGV("%s: bus device set volume called", __func__);
5535 if (!out->standby)
5536 ret = out_set_pcm_volume(stream, left, right);
5537 out->volume_l = left;
5538 out->volume_r = right;
5539 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005540 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005542 return -ENOSYS;
5543}
5544
Zhou Songc9672822017-08-16 16:01:39 +08005545static void update_frames_written(struct stream_out *out, size_t bytes)
5546{
5547 size_t bpf = 0;
5548
5549 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5550 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5551 bpf = 1;
5552 else if (!is_offload_usecase(out->usecase))
5553 bpf = audio_bytes_per_sample(out->format) *
5554 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005555
5556 pthread_mutex_lock(&out->position_query_lock);
5557 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005558 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005559 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5560 }
5561 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005562}
5563
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005564int split_and_write_audio_haptic_data(struct stream_out *out,
5565 const void *buffer, size_t bytes_to_write)
5566{
5567 struct audio_device *adev = out->dev;
5568
5569 int ret = 0;
5570 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5571 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5572 size_t frame_size = channel_count * bytes_per_sample;
5573 size_t frame_count = bytes_to_write / frame_size;
5574
5575 bool force_haptic_path =
5576 property_get_bool("vendor.audio.test_haptic", false);
5577
5578 // extract Haptics data from Audio buffer
5579 bool alloc_haptic_buffer = false;
5580 int haptic_channel_count = adev->haptics_config.channels;
5581 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5582 size_t audio_frame_size = frame_size - haptic_frame_size;
5583 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5584
5585 if (adev->haptic_buffer == NULL) {
5586 alloc_haptic_buffer = true;
5587 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5588 free(adev->haptic_buffer);
5589 adev->haptic_buffer_size = 0;
5590 alloc_haptic_buffer = true;
5591 }
5592
5593 if (alloc_haptic_buffer) {
5594 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005595 if(adev->haptic_buffer == NULL) {
5596 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5597 return -ENOMEM;
5598 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005599 adev->haptic_buffer_size = total_haptic_buffer_size;
5600 }
5601
5602 size_t src_index = 0, aud_index = 0, hap_index = 0;
5603 uint8_t *audio_buffer = (uint8_t *)buffer;
5604 uint8_t *haptic_buffer = adev->haptic_buffer;
5605
5606 // This is required for testing only. This works for stereo data only.
5607 // One channel is fed to audio stream and other to haptic stream for testing.
5608 if (force_haptic_path)
5609 audio_frame_size = haptic_frame_size = bytes_per_sample;
5610
5611 for (size_t i = 0; i < frame_count; i++) {
5612 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5613 audio_frame_size);
5614 aud_index += audio_frame_size;
5615 src_index += audio_frame_size;
5616
5617 if (adev->haptic_pcm)
5618 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5619 haptic_frame_size);
5620 hap_index += haptic_frame_size;
5621 src_index += haptic_frame_size;
5622
5623 // This is required for testing only.
5624 // Discard haptic channel data.
5625 if (force_haptic_path)
5626 src_index += haptic_frame_size;
5627 }
5628
5629 // write to audio pipeline
5630 ret = pcm_write(out->pcm, (void *)audio_buffer,
5631 frame_count * audio_frame_size);
5632
5633 // write to haptics pipeline
5634 if (adev->haptic_pcm)
5635 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5636 frame_count * haptic_frame_size);
5637
5638 return ret;
5639}
5640
Aalique Grahame22e49102018-12-18 14:23:57 -08005641#ifdef NO_AUDIO_OUT
5642static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5643 const void *buffer __unused, size_t bytes)
5644{
5645 struct stream_out *out = (struct stream_out *)stream;
5646
5647 /* No Output device supported other than BT for playback.
5648 * Sleep for the amount of buffer duration
5649 */
5650 lock_output_stream(out);
5651 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5652 (const struct audio_stream_out *)&out->stream) /
5653 out_get_sample_rate(&out->stream.common));
5654 pthread_mutex_unlock(&out->lock);
5655 return bytes;
5656}
5657#endif
5658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005659static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5660 size_t bytes)
5661{
5662 struct stream_out *out = (struct stream_out *)stream;
5663 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005664 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305665 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005666 const size_t frame_size = audio_stream_out_frame_size(stream);
5667 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305668 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005669 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005670
Haynes Mathew George380745d2017-10-04 15:27:45 -07005671 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005672 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305673
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305674 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005675
Dhananjay Kumarac341582017-02-23 23:42:25 +05305676 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305677 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305678 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5679 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005680 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305681 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305682 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305683 ALOGD(" %s: sound card is not active/SSR state", __func__);
5684 ret= -EIO;
5685 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305686 }
5687 }
5688
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305689 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305690 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305691 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305692 goto exit;
5693 }
5694
Haynes Mathew George16081042017-05-31 17:16:49 -07005695 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5696 ret = -EINVAL;
5697 goto exit;
5698 }
5699
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005700 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305701 !out->is_iec61937_info_available) {
5702
5703 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5704 out->is_iec61937_info_available = true;
5705 } else if (audio_extn_passthru_is_enabled()) {
5706 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305707 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305708
5709 if((out->format == AUDIO_FORMAT_DTS) ||
5710 (out->format == AUDIO_FORMAT_DTS_HD)) {
5711 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5712 buffer, bytes);
5713 if (ret) {
5714 if (ret != -ENOSYS) {
5715 out->is_iec61937_info_available = false;
5716 ALOGD("iec61937 transmission info not yet updated retry");
5717 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305718 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305719 /* if stream has started and after that there is
5720 * stream config change (iec transmission config)
5721 * then trigger select_device to update backend configuration.
5722 */
5723 out->stream_config_changed = true;
5724 pthread_mutex_lock(&adev->lock);
5725 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305726 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005727 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305728 ret = -EINVAL;
5729 goto exit;
5730 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305731 pthread_mutex_unlock(&adev->lock);
5732 out->stream_config_changed = false;
5733 out->is_iec61937_info_available = true;
5734 }
5735 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305736
Meng Wang4c32fb42020-01-16 17:57:11 +08005737#ifdef AUDIO_GKI_ENABLED
5738 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5739 compr_passthr = out->compr_config.codec->reserved[0];
5740#else
5741 compr_passthr = out->compr_config.codec->compr_passthr;
5742#endif
5743
Garmond Leung317cbf12017-09-13 16:20:50 -07005744 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005745 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305746 (out->is_iec61937_info_available == true)) {
5747 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5748 ret = -EINVAL;
5749 goto exit;
5750 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305751 }
5752 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305753
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005754 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005755 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005756 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5757 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305758 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305759 ret = -EIO;
5760 goto exit;
5761 }
5762 }
5763 }
5764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005765 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005766 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005767 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5768
Eric Laurent150dbfe2013-02-27 14:31:02 -08005769 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005770 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5771 ret = voice_extn_compress_voip_start_output_stream(out);
5772 else
5773 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005774 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005775 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005776 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005777 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005778 goto exit;
5779 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305780 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005781 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
vivek mehtab72d08d2016-04-29 03:16:47 -07005782 if (last_known_cal_step != -1) {
5783 ALOGD("%s: retry previous failed cal level set", __func__);
5784 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305785 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005786 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305787
5788 if ((out->is_iec61937_info_available == true) &&
5789 (audio_extn_passthru_is_passthrough_stream(out))&&
5790 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5791 ret = -EINVAL;
5792 goto exit;
5793 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305794 if (out->set_dual_mono)
5795 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005796
5797 // log startup time in ms.
5798 simple_stats_log(
5799 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005800 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005801
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005802 if (adev->is_channel_status_set == false &&
5803 compare_device_type(&out->device_list,
5804 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005805 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305806 adev->is_channel_status_set = true;
5807 }
5808
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305809 if ((adev->use_old_pspd_mix_ctrl == true) &&
5810 (out->pspd_coeff_sent == false)) {
5811 /*
5812 * Need to resend pspd coefficients after stream started for
5813 * older kernel version as it does not save the coefficients
5814 * and also stream has to be started for coeff to apply.
5815 */
5816 usecase = get_usecase_from_list(adev, out->usecase);
5817 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305818 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305819 out->pspd_coeff_sent = true;
5820 }
5821 }
5822
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005823 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005824 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005825 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005826 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005827 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5828 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305829 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5830 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005831 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305832 out->send_next_track_params = false;
5833 out->is_compr_metadata_avail = false;
5834 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005835 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305836 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305837 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005838
Ashish Jain83a6cc22016-06-28 14:34:17 +05305839 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305840 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305841 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305842 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005843 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305844 return -EINVAL;
5845 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305846 audio_format_t dst_format = out->hal_op_format;
5847 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305848
Dieter Luecking5d57def2018-09-07 14:23:37 +02005849 /* prevent division-by-zero */
5850 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5851 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5852 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5853 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305854 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005855 ATRACE_END();
5856 return -EINVAL;
5857 }
5858
Ashish Jainf1eaa582016-05-23 20:54:24 +05305859 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5860 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5861
Ashish Jain83a6cc22016-06-28 14:34:17 +05305862 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305863 dst_format,
5864 buffer,
5865 src_format,
5866 frames);
5867
Ashish Jain83a6cc22016-06-28 14:34:17 +05305868 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305869 bytes_to_write);
5870
5871 /*Convert written bytes in audio flinger format*/
5872 if (ret > 0)
5873 ret = ((ret * format_to_bitwidth_table[out->format]) /
5874 format_to_bitwidth_table[dst_format]);
5875 }
5876 } else
5877 ret = compress_write(out->compr, buffer, bytes);
5878
Zhou Songc9672822017-08-16 16:01:39 +08005879 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5880 update_frames_written(out, bytes);
5881
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305882 if (ret < 0)
5883 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005884 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305885 /*msg to cb thread only if non blocking write is enabled*/
5886 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305887 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005888 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305889 } else if (-ENETRESET == ret) {
5890 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305891 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305892 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305893 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005894 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305895 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005896 }
Ashish Jain5106d362016-05-11 19:23:33 +05305897
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305898 /* Call compr start only when non-zero bytes of data is there to be rendered */
5899 if (!out->playback_started && ret > 0) {
5900 int status = compress_start(out->compr);
5901 if (status < 0) {
5902 ret = status;
5903 ALOGE("%s: compr start failed with err %d", __func__, errno);
5904 goto exit;
5905 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005906 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005907 out->playback_started = 1;
5908 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005909
5910 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5911 popcount(out->channel_mask),
5912 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005913 }
5914 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005915 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005916 return ret;
5917 } else {
5918 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005919 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005920 if (out->muted)
5921 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005922 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5923 __func__, frames, frame_size, bytes_to_write);
5924
Aalique Grahame22e49102018-12-18 14:23:57 -08005925 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005926 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5927 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5928 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005929 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5930 int16_t *src = (int16_t *)buffer;
5931 int16_t *dst = (int16_t *)buffer;
5932
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005933 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005934 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005935 "out_write called for %s use case with wrong properties",
5936 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005937
5938 /*
5939 * FIXME: this can be removed once audio flinger mixer supports
5940 * mono output
5941 */
5942
5943 /*
5944 * Code below goes over each frame in the buffer and adds both
5945 * L and R samples and then divides by 2 to convert to mono
5946 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005947 if (channel_count == 2) {
5948 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5949 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5950 }
5951 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005952 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005953 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07005954
5955 // Note: since out_get_presentation_position() is called alternating with out_write()
5956 // by AudioFlinger, we can check underruns using the prior timestamp read.
5957 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
5958 if (out->last_fifo_valid) {
5959 // compute drain to see if there is an underrun.
5960 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
5961 const int64_t frames_by_time =
5962 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
5963 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
5964
5965 if (underrun > 0) {
5966 simple_stats_log(&out->fifo_underruns, underrun);
5967
5968 ALOGW("%s: underrun(%lld) "
5969 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
5970 __func__,
5971 (long long)out->fifo_underruns.n,
5972 (long long)frames_by_time,
5973 (long long)out->last_fifo_frames_remaining);
5974 }
5975 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
5976 }
5977
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305978 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005979
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005980 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005981
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005982 if (out->config.rate)
5983 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5984 out->config.rate;
5985
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005986 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005987 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5988
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005989 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005990 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005991 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305992 out->convert_buffer != NULL) {
5993
5994 memcpy_by_audio_format(out->convert_buffer,
5995 out->hal_op_format,
5996 buffer,
5997 out->hal_ip_format,
5998 out->config.period_size * out->config.channels);
5999
6000 ret = pcm_write(out->pcm, out->convert_buffer,
6001 (out->config.period_size *
6002 out->config.channels *
6003 format_to_bitwidth_table[out->hal_op_format]));
6004 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306005 /*
6006 * To avoid underrun in DSP when the application is not pumping
6007 * data at required rate, check for the no. of bytes and ignore
6008 * pcm_write if it is less than actual buffer size.
6009 * It is a work around to a change in compress VOIP driver.
6010 */
6011 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6012 bytes < (out->config.period_size * out->config.channels *
6013 audio_bytes_per_sample(out->format))) {
6014 size_t voip_buf_size =
6015 out->config.period_size * out->config.channels *
6016 audio_bytes_per_sample(out->format);
6017 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6018 __func__, bytes, voip_buf_size);
6019 usleep(((uint64_t)voip_buf_size - bytes) *
6020 1000000 / audio_stream_out_frame_size(stream) /
6021 out_get_sample_rate(&out->stream.common));
6022 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006023 } else {
6024 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6025 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6026 else
6027 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6028 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306029 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006030
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006031 release_out_focus(out);
6032
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306033 if (ret < 0)
6034 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006035 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306036 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006037 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006038 }
6039
6040exit:
Zhou Songc9672822017-08-16 16:01:39 +08006041 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306042 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306043 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306044 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006045 pthread_mutex_unlock(&out->lock);
6046
6047 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006048 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006049 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306050 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306051 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306052 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306053 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306054 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306055 out->standby = true;
6056 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306057 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006058 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6059 /* prevent division-by-zero */
6060 uint32_t stream_size = audio_stream_out_frame_size(stream);
6061 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006062
Dieter Luecking5d57def2018-09-07 14:23:37 +02006063 if ((stream_size == 0) || (srate == 0)) {
6064 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6065 ATRACE_END();
6066 return -EINVAL;
6067 }
6068 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6069 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006070 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306071 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006072 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006073 return ret;
6074 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006075 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006076 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006077 return bytes;
6078}
6079
6080static int out_get_render_position(const struct audio_stream_out *stream,
6081 uint32_t *dsp_frames)
6082{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006083 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006084
6085 if (dsp_frames == NULL)
6086 return -EINVAL;
6087
6088 *dsp_frames = 0;
6089 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006090 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306091
6092 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6093 * this operation and adev_close_output_stream(where out gets reset).
6094 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306095 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006096 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306097 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006098 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306099 return 0;
6100 }
6101
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006102 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306103 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306104 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006105 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306106 if (ret < 0)
6107 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006108 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306109 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006110 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306111 if (-ENETRESET == ret) {
6112 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306113 out->card_status = CARD_STATUS_OFFLINE;
6114 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306115 } else if(ret < 0) {
6116 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306117 ret = -EINVAL;
6118 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306119 /*
6120 * Handle corner case where compress session is closed during SSR
6121 * and timestamp is queried
6122 */
6123 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306124 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306125 } else if (out->prev_card_status_offline) {
6126 ALOGE("ERROR: previously sound card was offline,return error");
6127 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306128 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306129 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006130 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306131 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306132 pthread_mutex_unlock(&out->lock);
6133 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006134 } else if (audio_is_linear_pcm(out->format)) {
6135 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006136 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006137 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006138 } else
6139 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006140}
6141
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006142static int out_add_audio_effect(const struct audio_stream *stream __unused,
6143 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006144{
6145 return 0;
6146}
6147
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006148static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6149 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006150{
6151 return 0;
6152}
6153
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006154static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6155 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006156{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306157 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006158}
6159
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006160static int out_get_presentation_position(const struct audio_stream_out *stream,
6161 uint64_t *frames, struct timespec *timestamp)
6162{
6163 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306164 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006165 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006166
Ashish Jain5106d362016-05-11 19:23:33 +05306167 /* below piece of code is not guarded against any lock because audioFliner serializes
6168 * this operation and adev_close_output_stream( where out gets reset).
6169 */
6170 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306171 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006172 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306173 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6174 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6175 return 0;
6176 }
6177
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006178 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006179
Ashish Jain5106d362016-05-11 19:23:33 +05306180 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6181 ret = compress_get_tstamp(out->compr, &dsp_frames,
6182 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006183 // Adjustment accounts for A2dp encoder latency with offload usecases
6184 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006185 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006186 unsigned long offset =
6187 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6188 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6189 }
Ashish Jain5106d362016-05-11 19:23:33 +05306190 ALOGVV("%s rendered frames %ld sample_rate %d",
6191 __func__, dsp_frames, out->sample_rate);
6192 *frames = dsp_frames;
6193 if (ret < 0)
6194 ret = -errno;
6195 if (-ENETRESET == ret) {
6196 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306197 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306198 ret = -EINVAL;
6199 } else
6200 ret = 0;
6201 /* this is the best we can do */
6202 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006203 } else {
6204 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006205 unsigned int avail;
6206 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006207 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006208 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006209
Andy Hunga1f48fa2019-07-01 18:14:53 -07006210 if (out->kernel_buffer_size > avail) {
6211 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6212 } else {
6213 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6214 __func__, avail, out->kernel_buffer_size);
6215 avail = out->kernel_buffer_size;
6216 frames_temp = out->last_fifo_frames_remaining = 0;
6217 }
6218 out->last_fifo_valid = true;
6219 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6220
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006221 if (out->written >= frames_temp)
6222 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006223
Andy Hunga1f48fa2019-07-01 18:14:53 -07006224 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6225 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6226
Weiyin Jiangd4633762018-03-16 12:05:03 +08006227 // This adjustment accounts for buffering after app processor.
6228 // It is based on estimated DSP latency per use case, rather than exact.
Robert Lee58215542019-07-15 20:55:12 +08006229 pthread_mutex_lock(&adev->lock);
6230 frames_temp = platform_render_latency(out->dev, out->usecase) *
6231 out->sample_rate / 1000000LL;
6232 pthread_mutex_unlock(&adev->lock);
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006233 if (signed_frames >= frames_temp)
6234 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006235
Weiyin Jiangd4633762018-03-16 12:05:03 +08006236 // Adjustment accounts for A2dp encoder latency with non offload usecases
6237 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006238 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006239 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6240 if (signed_frames >= frames_temp)
6241 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006242 }
6243
6244 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006245 *frames = signed_frames;
6246 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006247 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006248 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6249 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006250 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306251 *frames = out->written;
6252 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306253 if (is_offload_usecase(out->usecase))
6254 ret = -EINVAL;
6255 else
6256 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006257 }
6258 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006259 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006260 return ret;
6261}
6262
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006263static int out_set_callback(struct audio_stream_out *stream,
6264 stream_callback_t callback, void *cookie)
6265{
6266 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006267 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006268
6269 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006270 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006271 out->client_callback = callback;
6272 out->client_cookie = cookie;
6273 if (out->adsp_hdlr_stream_handle) {
6274 ret = audio_extn_adsp_hdlr_stream_set_callback(
6275 out->adsp_hdlr_stream_handle,
6276 callback,
6277 cookie);
6278 if (ret)
6279 ALOGW("%s:adsp hdlr callback registration failed %d",
6280 __func__, ret);
6281 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006282 pthread_mutex_unlock(&out->lock);
6283 return 0;
6284}
6285
6286static int out_pause(struct audio_stream_out* stream)
6287{
6288 struct stream_out *out = (struct stream_out *)stream;
6289 int status = -ENOSYS;
6290 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006291 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006292 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306293 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006294 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006295 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306296 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306297 status = compress_pause(out->compr);
6298
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006299 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006300
Mingming Yin21854652016-04-13 11:54:02 -07006301 if (audio_extn_passthru_is_active()) {
6302 ALOGV("offload use case, pause passthru");
6303 audio_extn_passthru_on_pause(out);
6304 }
6305
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306306 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006307 audio_extn_dts_notify_playback_state(out->usecase, 0,
6308 out->sample_rate, popcount(out->channel_mask),
6309 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006310 }
6311 pthread_mutex_unlock(&out->lock);
6312 }
6313 return status;
6314}
6315
6316static int out_resume(struct audio_stream_out* stream)
6317{
6318 struct stream_out *out = (struct stream_out *)stream;
6319 int status = -ENOSYS;
6320 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006321 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006322 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306323 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006324 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006325 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306326 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306327 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006328 }
6329 if (!status) {
6330 out->offload_state = OFFLOAD_STATE_PLAYING;
6331 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306332 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006333 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6334 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006335 }
6336 pthread_mutex_unlock(&out->lock);
6337 }
6338 return status;
6339}
6340
6341static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6342{
6343 struct stream_out *out = (struct stream_out *)stream;
6344 int status = -ENOSYS;
6345 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006346 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006347 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006348 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6349 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6350 else
6351 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6352 pthread_mutex_unlock(&out->lock);
6353 }
6354 return status;
6355}
6356
6357static int out_flush(struct audio_stream_out* stream)
6358{
6359 struct stream_out *out = (struct stream_out *)stream;
6360 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006361 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006362 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006363 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006364 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6365 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006366 } else {
6367 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6368 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006369 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006370 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006371 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006372 return 0;
6373 }
6374 return -ENOSYS;
6375}
6376
Haynes Mathew George16081042017-05-31 17:16:49 -07006377static int out_stop(const struct audio_stream_out* stream)
6378{
6379 struct stream_out *out = (struct stream_out *)stream;
6380 struct audio_device *adev = out->dev;
6381 int ret = -ENOSYS;
6382
6383 ALOGV("%s", __func__);
6384 pthread_mutex_lock(&adev->lock);
6385 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6386 out->playback_started && out->pcm != NULL) {
6387 pcm_stop(out->pcm);
6388 ret = stop_output_stream(out);
6389 out->playback_started = false;
6390 }
6391 pthread_mutex_unlock(&adev->lock);
6392 return ret;
6393}
6394
6395static int out_start(const struct audio_stream_out* stream)
6396{
6397 struct stream_out *out = (struct stream_out *)stream;
6398 struct audio_device *adev = out->dev;
6399 int ret = -ENOSYS;
6400
6401 ALOGV("%s", __func__);
6402 pthread_mutex_lock(&adev->lock);
6403 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6404 !out->playback_started && out->pcm != NULL) {
6405 ret = start_output_stream(out);
6406 if (ret == 0) {
6407 out->playback_started = true;
6408 }
6409 }
6410 pthread_mutex_unlock(&adev->lock);
6411 return ret;
6412}
6413
6414/*
6415 * Modify config->period_count based on min_size_frames
6416 */
6417static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6418{
6419 int periodCountRequested = (min_size_frames + config->period_size - 1)
6420 / config->period_size;
6421 int periodCount = MMAP_PERIOD_COUNT_MIN;
6422
6423 ALOGV("%s original config.period_size = %d config.period_count = %d",
6424 __func__, config->period_size, config->period_count);
6425
6426 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6427 periodCount *= 2;
6428 }
6429 config->period_count = periodCount;
6430
6431 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6432}
6433
Phil Burkfe17efd2019-03-25 10:23:35 -07006434// Read offset for the positional timestamp from a persistent vendor property.
6435// This is to workaround apparent inaccuracies in the timing information that
6436// is used by the AAudio timing model. The inaccuracies can cause glitches.
6437static int64_t get_mmap_out_time_offset() {
6438 const int32_t kDefaultOffsetMicros = 0;
6439 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006440 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006441 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6442 return mmap_time_offset_micros * (int64_t)1000;
6443}
6444
Haynes Mathew George16081042017-05-31 17:16:49 -07006445static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6446 int32_t min_size_frames,
6447 struct audio_mmap_buffer_info *info)
6448{
6449 struct stream_out *out = (struct stream_out *)stream;
6450 struct audio_device *adev = out->dev;
6451 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006452 unsigned int offset1 = 0;
6453 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006454 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006455 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006456 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006457
Arun Mirpuri5d170872019-03-26 13:21:31 -07006458 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306459 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006460 pthread_mutex_lock(&adev->lock);
6461
Sharad Sanglec6f32552018-05-04 16:15:38 +05306462 if (CARD_STATUS_OFFLINE == out->card_status ||
6463 CARD_STATUS_OFFLINE == adev->card_status) {
6464 ALOGW("out->card_status or adev->card_status offline, try again");
6465 ret = -EIO;
6466 goto exit;
6467 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306468 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006469 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6470 ret = -EINVAL;
6471 goto exit;
6472 }
6473 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6474 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6475 ret = -ENOSYS;
6476 goto exit;
6477 }
6478 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6479 if (out->pcm_device_id < 0) {
6480 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6481 __func__, out->pcm_device_id, out->usecase);
6482 ret = -EINVAL;
6483 goto exit;
6484 }
6485
6486 adjust_mmap_period_count(&out->config, min_size_frames);
6487
Arun Mirpuri5d170872019-03-26 13:21:31 -07006488 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006489 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6490 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6491 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306492 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306493 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6494 out->card_status = CARD_STATUS_OFFLINE;
6495 adev->card_status = CARD_STATUS_OFFLINE;
6496 ret = -EIO;
6497 goto exit;
6498 }
6499
Haynes Mathew George16081042017-05-31 17:16:49 -07006500 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6501 step = "open";
6502 ret = -ENODEV;
6503 goto exit;
6504 }
6505 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6506 if (ret < 0) {
6507 step = "begin";
6508 goto exit;
6509 }
juyuchen626833d2019-06-04 16:48:02 +08006510
6511 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006512 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006513 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006514 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006515 ret = platform_get_mmap_data_fd(adev->platform,
6516 out->pcm_device_id, 0 /*playback*/,
6517 &info->shared_memory_fd,
6518 &mmap_size);
6519 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006520 // Fall back to non exclusive mode
6521 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6522 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006523 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6524 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6525
Arun Mirpuri5d170872019-03-26 13:21:31 -07006526 if (mmap_size < buffer_size) {
6527 step = "mmap";
6528 goto exit;
6529 }
juyuchen626833d2019-06-04 16:48:02 +08006530 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006531 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006532 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006533 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006534
6535 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6536 if (ret < 0) {
6537 step = "commit";
6538 goto exit;
6539 }
6540
Phil Burkfe17efd2019-03-25 10:23:35 -07006541 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6542
Haynes Mathew George16081042017-05-31 17:16:49 -07006543 out->standby = false;
6544 ret = 0;
6545
Arun Mirpuri5d170872019-03-26 13:21:31 -07006546 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006547 __func__, info->shared_memory_address, info->buffer_size_frames);
6548
6549exit:
6550 if (ret != 0) {
6551 if (out->pcm == NULL) {
6552 ALOGE("%s: %s - %d", __func__, step, ret);
6553 } else {
6554 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6555 pcm_close(out->pcm);
6556 out->pcm = NULL;
6557 }
6558 }
6559 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306560 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006561 return ret;
6562}
6563
6564static int out_get_mmap_position(const struct audio_stream_out *stream,
6565 struct audio_mmap_position *position)
6566{
6567 struct stream_out *out = (struct stream_out *)stream;
6568 ALOGVV("%s", __func__);
6569 if (position == NULL) {
6570 return -EINVAL;
6571 }
6572 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006573 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006574 return -ENOSYS;
6575 }
6576 if (out->pcm == NULL) {
6577 return -ENOSYS;
6578 }
6579
6580 struct timespec ts = { 0, 0 };
6581 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6582 if (ret < 0) {
6583 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6584 return ret;
6585 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006586 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6587 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006588 return 0;
6589}
6590
6591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006592/** audio_stream_in implementation **/
6593static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6594{
6595 struct stream_in *in = (struct stream_in *)stream;
6596
6597 return in->config.rate;
6598}
6599
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006600static int in_set_sample_rate(struct audio_stream *stream __unused,
6601 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006602{
6603 return -ENOSYS;
6604}
6605
6606static size_t in_get_buffer_size(const struct audio_stream *stream)
6607{
6608 struct stream_in *in = (struct stream_in *)stream;
6609
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006610 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6611 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006612 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6613 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306614 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306615 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006616
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006617 return in->config.period_size * in->af_period_multiplier *
6618 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006619}
6620
6621static uint32_t in_get_channels(const struct audio_stream *stream)
6622{
6623 struct stream_in *in = (struct stream_in *)stream;
6624
6625 return in->channel_mask;
6626}
6627
6628static audio_format_t in_get_format(const struct audio_stream *stream)
6629{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006630 struct stream_in *in = (struct stream_in *)stream;
6631
6632 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006633}
6634
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006635static int in_set_format(struct audio_stream *stream __unused,
6636 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006637{
6638 return -ENOSYS;
6639}
6640
6641static int in_standby(struct audio_stream *stream)
6642{
6643 struct stream_in *in = (struct stream_in *)stream;
6644 struct audio_device *adev = in->dev;
6645 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306646 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6647 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006648 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306649
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006650 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006651 if (!in->standby && in->is_st_session) {
6652 ALOGD("%s: sound trigger pcm stop lab", __func__);
6653 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006654 if (adev->num_va_sessions > 0)
6655 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006656 in->standby = 1;
6657 }
6658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006659 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006660 if (adev->adm_deregister_stream)
6661 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6662
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006663 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006664 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006665 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006666 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006667 voice_extn_compress_voip_close_input_stream(stream);
6668 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006669 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6670 do_stop = in->capture_started;
6671 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006672 if (in->mmap_shared_memory_fd >= 0) {
6673 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6674 __func__, in->mmap_shared_memory_fd);
6675 close(in->mmap_shared_memory_fd);
6676 in->mmap_shared_memory_fd = -1;
6677 }
Zhou Songa8895042016-07-05 17:54:22 +08006678 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306679 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306680 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006681 }
6682
Arun Mirpuri5d170872019-03-26 13:21:31 -07006683 if (in->pcm) {
6684 ATRACE_BEGIN("pcm_in_close");
6685 pcm_close(in->pcm);
6686 ATRACE_END();
6687 in->pcm = NULL;
6688 }
6689
Carter Hsu2e429db2019-05-14 18:50:52 +08006690 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006691 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006692
George Gao3018ede2019-10-23 13:23:00 -07006693 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6694 if (adev->num_va_sessions > 0)
6695 adev->num_va_sessions--;
6696 }
Quinn Malef6050362019-01-30 15:55:40 -08006697
Eric Laurent150dbfe2013-02-27 14:31:02 -08006698 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006699 }
6700 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006701 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006702 return status;
6703}
6704
Aalique Grahame22e49102018-12-18 14:23:57 -08006705static int in_dump(const struct audio_stream *stream,
6706 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006707{
Aalique Grahame22e49102018-12-18 14:23:57 -08006708 struct stream_in *in = (struct stream_in *)stream;
6709
6710 // We try to get the lock for consistency,
6711 // but it isn't necessary for these variables.
6712 // If we're not in standby, we may be blocked on a read.
6713 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6714 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6715 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6716 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6717
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006718 char buffer[256]; // for statistics formatting
6719 if (in->start_latency_ms.n > 0) {
6720 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6721 dprintf(fd, " Start latency ms: %s\n", buffer);
6722 }
6723
Aalique Grahame22e49102018-12-18 14:23:57 -08006724 if (locked) {
6725 pthread_mutex_unlock(&in->lock);
6726 }
6727
6728 // dump error info
6729 (void)error_log_dump(
6730 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6731
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006732 return 0;
6733}
6734
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306735static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6736{
6737 if (!stream || !parms)
6738 return;
6739
6740 struct stream_in *in = (struct stream_in *)stream;
6741 struct audio_device *adev = in->dev;
6742
6743 card_status_t status;
6744 int card;
6745 if (parse_snd_card_status(parms, &card, &status) < 0)
6746 return;
6747
6748 pthread_mutex_lock(&adev->lock);
6749 bool valid_cb = (card == adev->snd_card);
6750 pthread_mutex_unlock(&adev->lock);
6751
6752 if (!valid_cb)
6753 return;
6754
6755 lock_input_stream(in);
6756 if (in->card_status != status)
6757 in->card_status = status;
6758 pthread_mutex_unlock(&in->lock);
6759
6760 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6761 use_case_table[in->usecase],
6762 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6763
6764 // a better solution would be to report error back to AF and let
6765 // it put the stream to standby
6766 if (status == CARD_STATUS_OFFLINE)
6767 in_standby(&in->stream.common);
6768
6769 return;
6770}
6771
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006772int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006773 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006774 audio_source_t source)
6775{
6776 struct audio_device *adev = in->dev;
6777 int ret = 0;
6778
6779 lock_input_stream(in);
6780 pthread_mutex_lock(&adev->lock);
6781
6782 /* no audio source uses val == 0 */
6783 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6784 in->source = source;
6785 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6786 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6787 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6788 (in->config.rate == 8000 || in->config.rate == 16000 ||
6789 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6790 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6791 ret = voice_extn_compress_voip_open_input_stream(in);
6792 if (ret != 0) {
6793 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6794 __func__, ret);
6795 }
6796 }
6797 }
6798
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006799 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6800 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006801 // Workaround: If routing to an non existing usb device, fail gracefully
6802 // The routing request will otherwise block during 10 second
6803 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006804 struct str_parms *usb_addr =
6805 str_parms_create_str(get_usb_device_address(devices));
6806 if (is_usb_in_device_type(devices) && usb_addr &&
6807 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006808 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6809 ret = -ENOSYS;
6810 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006811 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006812 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006813 if (!in->standby && !in->is_st_session) {
6814 ALOGV("update input routing change");
6815 // inform adm before actual routing to prevent glitches.
6816 if (adev->adm_on_routing_change) {
6817 adev->adm_on_routing_change(adev->adm_data,
6818 in->capture_handle);
6819 ret = select_devices(adev, in->usecase);
6820 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6821 adev->adm_routing_changed = true;
6822 }
6823 }
6824 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006825 if (usb_addr)
6826 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006827 }
6828 pthread_mutex_unlock(&adev->lock);
6829 pthread_mutex_unlock(&in->lock);
6830
6831 ALOGD("%s: exit: status(%d)", __func__, ret);
6832 return ret;
6833}
6834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006835static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6836{
6837 struct stream_in *in = (struct stream_in *)stream;
6838 struct audio_device *adev = in->dev;
6839 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006840 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306841 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006842
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306843 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006844 parms = str_parms_create_str(kvpairs);
6845
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306846 if (!parms)
6847 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006848 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006849 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006850
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306851 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6852 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306853 strlcpy(in->profile, value, sizeof(in->profile));
6854 ALOGV("updating stream profile with value '%s'", in->profile);
6855 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6856 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006857 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306858 in->sample_rate, in->bit_width,
6859 in->profile, &in->app_type_cfg);
6860 }
6861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006862 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006863 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006864
6865 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306866error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306867 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006868}
6869
6870static char* in_get_parameters(const struct audio_stream *stream,
6871 const char *keys)
6872{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006873 struct stream_in *in = (struct stream_in *)stream;
6874 struct str_parms *query = str_parms_create_str(keys);
6875 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006876 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006877
6878 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006879 if (reply) {
6880 str_parms_destroy(reply);
6881 }
6882 if (query) {
6883 str_parms_destroy(query);
6884 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006885 ALOGE("in_get_parameters: failed to create query or reply");
6886 return NULL;
6887 }
6888
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006889 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006890
6891 voice_extn_in_get_parameters(in, query, reply);
6892
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006893 stream_get_parameter_channels(query, reply,
6894 &in->supported_channel_masks[0]);
6895 stream_get_parameter_formats(query, reply,
6896 &in->supported_formats[0]);
6897 stream_get_parameter_rates(query, reply,
6898 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006899 str = str_parms_to_str(reply);
6900 str_parms_destroy(query);
6901 str_parms_destroy(reply);
6902
6903 ALOGV("%s: exit: returns - %s", __func__, str);
6904 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006905}
6906
Aalique Grahame22e49102018-12-18 14:23:57 -08006907static int in_set_gain(struct audio_stream_in *stream,
6908 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006909{
Aalique Grahame22e49102018-12-18 14:23:57 -08006910 struct stream_in *in = (struct stream_in *)stream;
6911 char mixer_ctl_name[128];
6912 struct mixer_ctl *ctl;
6913 int ctl_value;
6914
6915 ALOGV("%s: gain %f", __func__, gain);
6916
6917 if (stream == NULL)
6918 return -EINVAL;
6919
6920 /* in_set_gain() only used to silence MMAP capture for now */
6921 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6922 return -ENOSYS;
6923
6924 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6925
6926 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6927 if (!ctl) {
6928 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6929 __func__, mixer_ctl_name);
6930 return -ENOSYS;
6931 }
6932
6933 if (gain < RECORD_GAIN_MIN)
6934 gain = RECORD_GAIN_MIN;
6935 else if (gain > RECORD_GAIN_MAX)
6936 gain = RECORD_GAIN_MAX;
6937 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6938
6939 mixer_ctl_set_value(ctl, 0, ctl_value);
6940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006941 return 0;
6942}
6943
6944static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6945 size_t bytes)
6946{
6947 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306948
6949 if (in == NULL) {
6950 ALOGE("%s: stream_in ptr is NULL", __func__);
6951 return -EINVAL;
6952 }
6953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006954 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306955 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306956 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006957
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006958 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306959
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006960 if (in->is_st_session) {
6961 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6962 /* Read from sound trigger HAL */
6963 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006964 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006965 if (adev->num_va_sessions < UINT_MAX)
6966 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006967 in->standby = 0;
6968 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006969 pthread_mutex_unlock(&in->lock);
6970 return bytes;
6971 }
6972
Haynes Mathew George16081042017-05-31 17:16:49 -07006973 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6974 ret = -ENOSYS;
6975 goto exit;
6976 }
6977
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006978 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6979 !in->standby && adev->adm_routing_changed) {
6980 ret = -ENOSYS;
6981 goto exit;
6982 }
6983
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006984 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006985 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6986
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006987 pthread_mutex_lock(&adev->lock);
6988 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6989 ret = voice_extn_compress_voip_start_input_stream(in);
6990 else
6991 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006992 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6993 if (adev->num_va_sessions < UINT_MAX)
6994 adev->num_va_sessions++;
6995 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006996 pthread_mutex_unlock(&adev->lock);
6997 if (ret != 0) {
6998 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006999 }
7000 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007001
7002 // log startup time in ms.
7003 simple_stats_log(
7004 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007005 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007006
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307007 /* Avoid read if capture_stopped is set */
7008 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7009 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7010 ret = -EINVAL;
7011 goto exit;
7012 }
7013
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007014 // what's the duration requested by the client?
7015 long ns = 0;
7016
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307017 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007018 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7019 in->config.rate;
7020
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007021 ret = request_in_focus(in, ns);
7022 if (ret != 0)
7023 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007024 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007025
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307026 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307027 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7028 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307029 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007030 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307031 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007032 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007033 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007034 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007035 } else if (audio_extn_ffv_get_stream() == in) {
7036 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307037 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007038 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307039 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7040 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7041 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7042 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307043 ret = -EINVAL;
7044 goto exit;
7045 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307046 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307047 ret = -errno;
7048 }
7049 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307050 /* bytes read is always set to bytes for non compress usecases */
7051 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007052 }
7053
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007054 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007055
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007056 /*
Quinn Malef6050362019-01-30 15:55:40 -08007057 * Instead of writing zeroes here, we could trust the hardware to always
7058 * provide zeroes when muted. This is also muted with voice recognition
7059 * usecases so that other clients do not have access to voice recognition
7060 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007061 */
Quinn Malef6050362019-01-30 15:55:40 -08007062 if ((ret == 0 && voice_get_mic_mute(adev) &&
7063 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007064 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7065 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007066 (adev->num_va_sessions &&
7067 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7068 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7069 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007070 memset(buffer, 0, bytes);
7071
7072exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307073 frame_size = audio_stream_in_frame_size(stream);
7074 if (frame_size > 0)
7075 in->frames_read += bytes_read/frame_size;
7076
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007077 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307078 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007079 pthread_mutex_unlock(&in->lock);
7080
7081 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307082 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307083 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307084 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307085 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307086 in->standby = true;
7087 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307088 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307089 bytes_read = bytes;
7090 memset(buffer, 0, bytes);
7091 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007092 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007093 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7094 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007095 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307096 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307097 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007098 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307099 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007100}
7101
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007102static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007103{
7104 return 0;
7105}
7106
Aalique Grahame22e49102018-12-18 14:23:57 -08007107static int in_get_capture_position(const struct audio_stream_in *stream,
7108 int64_t *frames, int64_t *time)
7109{
7110 if (stream == NULL || frames == NULL || time == NULL) {
7111 return -EINVAL;
7112 }
7113 struct stream_in *in = (struct stream_in *)stream;
7114 int ret = -ENOSYS;
7115
7116 lock_input_stream(in);
7117 // note: ST sessions do not close the alsa pcm driver synchronously
7118 // on standby. Therefore, we may return an error even though the
7119 // pcm stream is still opened.
7120 if (in->standby) {
7121 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7122 "%s stream in standby but pcm not NULL for non ST session", __func__);
7123 goto exit;
7124 }
7125 if (in->pcm) {
7126 struct timespec timestamp;
7127 unsigned int avail;
7128 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7129 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007130 pthread_mutex_lock(&adev->lock);
7131 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
7132 - platform_capture_latency(in->dev, in->usecase) * 1000LL;
7133 pthread_mutex_unlock(&adev->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08007134 ret = 0;
7135 }
7136 }
7137exit:
7138 pthread_mutex_unlock(&in->lock);
7139 return ret;
7140}
7141
Carter Hsu2e429db2019-05-14 18:50:52 +08007142static int in_update_effect_list(bool add, effect_handle_t effect,
7143 struct listnode *head)
7144{
7145 struct listnode *node;
7146 struct in_effect_list *elist = NULL;
7147 struct in_effect_list *target = NULL;
7148 int ret = 0;
7149
7150 if (!head)
7151 return ret;
7152
7153 list_for_each(node, head) {
7154 elist = node_to_item(node, struct in_effect_list, list);
7155 if (elist->handle == effect) {
7156 target = elist;
7157 break;
7158 }
7159 }
7160
7161 if (add) {
7162 if (target) {
7163 ALOGD("effect %p already exist", effect);
7164 return ret;
7165 }
7166
7167 target = (struct in_effect_list *)
7168 calloc(1, sizeof(struct in_effect_list));
7169
7170 if (!target) {
7171 ALOGE("%s:fail to allocate memory", __func__);
7172 return -ENOMEM;
7173 }
7174
7175 target->handle = effect;
7176 list_add_tail(head, &target->list);
7177 } else {
7178 if (target) {
7179 list_remove(&target->list);
7180 free(target);
7181 }
7182 }
7183
7184 return ret;
7185}
7186
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007187static int add_remove_audio_effect(const struct audio_stream *stream,
7188 effect_handle_t effect,
7189 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007190{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007191 struct stream_in *in = (struct stream_in *)stream;
7192 int status = 0;
7193 effect_descriptor_t desc;
7194
7195 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007196 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7197
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007198 if (status != 0)
7199 return status;
7200
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007201 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007202 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007203 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007204 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7205 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007206 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007207
7208 in_update_effect_list(enable, effect, &in->aec_list);
7209 enable = !list_empty(&in->aec_list);
7210 if (enable == in->enable_aec)
7211 goto exit;
7212
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007213 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007214 ALOGD("AEC enable %d", enable);
7215
Aalique Grahame22e49102018-12-18 14:23:57 -08007216 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7217 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7218 in->dev->enable_voicerx = enable;
7219 struct audio_usecase *usecase;
7220 struct listnode *node;
7221 list_for_each(node, &in->dev->usecase_list) {
7222 usecase = node_to_item(node, struct audio_usecase, list);
7223 if (usecase->type == PCM_PLAYBACK)
7224 select_devices(in->dev, usecase->id);
7225 }
7226 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007227 if (!in->standby) {
7228 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7229 select_devices(in->dev, in->usecase);
7230 }
7231
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007232 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007233 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7234
7235 in_update_effect_list(enable, effect, &in->ns_list);
7236 enable = !list_empty(&in->ns_list);
7237 if (enable == in->enable_ns)
7238 goto exit;
7239
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007240 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007241 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007242 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007243 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7244 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007245 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7246 select_devices(in->dev, in->usecase);
7247 } else
7248 select_devices(in->dev, in->usecase);
7249 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007250 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007251exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007252 pthread_mutex_unlock(&in->dev->lock);
7253 pthread_mutex_unlock(&in->lock);
7254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007255 return 0;
7256}
7257
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007258static int in_add_audio_effect(const struct audio_stream *stream,
7259 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007260{
Eric Laurent994a6932013-07-17 11:51:42 -07007261 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007262 return add_remove_audio_effect(stream, effect, true);
7263}
7264
7265static int in_remove_audio_effect(const struct audio_stream *stream,
7266 effect_handle_t effect)
7267{
Eric Laurent994a6932013-07-17 11:51:42 -07007268 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007269 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007270}
7271
Derek Chenf939fb72018-11-13 13:34:41 -08007272streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7273 audio_io_handle_t input)
7274{
7275 struct listnode *node;
7276
7277 list_for_each(node, &dev->active_inputs_list) {
7278 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7279 streams_input_ctxt_t,
7280 list);
7281 if (in_ctxt->input->capture_handle == input) {
7282 return in_ctxt;
7283 }
7284 }
7285 return NULL;
7286}
7287
7288streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7289 audio_io_handle_t output)
7290{
7291 struct listnode *node;
7292
7293 list_for_each(node, &dev->active_outputs_list) {
7294 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7295 streams_output_ctxt_t,
7296 list);
7297 if (out_ctxt->output->handle == output) {
7298 return out_ctxt;
7299 }
7300 }
7301 return NULL;
7302}
7303
Haynes Mathew George16081042017-05-31 17:16:49 -07007304static int in_stop(const struct audio_stream_in* stream)
7305{
7306 struct stream_in *in = (struct stream_in *)stream;
7307 struct audio_device *adev = in->dev;
7308
7309 int ret = -ENOSYS;
7310 ALOGV("%s", __func__);
7311 pthread_mutex_lock(&adev->lock);
7312 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7313 in->capture_started && in->pcm != NULL) {
7314 pcm_stop(in->pcm);
7315 ret = stop_input_stream(in);
7316 in->capture_started = false;
7317 }
7318 pthread_mutex_unlock(&adev->lock);
7319 return ret;
7320}
7321
7322static int in_start(const struct audio_stream_in* stream)
7323{
7324 struct stream_in *in = (struct stream_in *)stream;
7325 struct audio_device *adev = in->dev;
7326 int ret = -ENOSYS;
7327
7328 ALOGV("%s in %p", __func__, in);
7329 pthread_mutex_lock(&adev->lock);
7330 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7331 !in->capture_started && in->pcm != NULL) {
7332 if (!in->capture_started) {
7333 ret = start_input_stream(in);
7334 if (ret == 0) {
7335 in->capture_started = true;
7336 }
7337 }
7338 }
7339 pthread_mutex_unlock(&adev->lock);
7340 return ret;
7341}
7342
Phil Burke0a86d12019-02-16 22:28:11 -08007343// Read offset for the positional timestamp from a persistent vendor property.
7344// This is to workaround apparent inaccuracies in the timing information that
7345// is used by the AAudio timing model. The inaccuracies can cause glitches.
7346static int64_t in_get_mmap_time_offset() {
7347 const int32_t kDefaultOffsetMicros = 0;
7348 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007349 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007350 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7351 return mmap_time_offset_micros * (int64_t)1000;
7352}
7353
Haynes Mathew George16081042017-05-31 17:16:49 -07007354static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7355 int32_t min_size_frames,
7356 struct audio_mmap_buffer_info *info)
7357{
7358 struct stream_in *in = (struct stream_in *)stream;
7359 struct audio_device *adev = in->dev;
7360 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007361 unsigned int offset1 = 0;
7362 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007363 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007364 uint32_t mmap_size = 0;
7365 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007366
7367 pthread_mutex_lock(&adev->lock);
7368 ALOGV("%s in %p", __func__, in);
7369
Sharad Sanglec6f32552018-05-04 16:15:38 +05307370 if (CARD_STATUS_OFFLINE == in->card_status||
7371 CARD_STATUS_OFFLINE == adev->card_status) {
7372 ALOGW("in->card_status or adev->card_status offline, try again");
7373 ret = -EIO;
7374 goto exit;
7375 }
7376
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307377 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007378 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7379 ret = -EINVAL;
7380 goto exit;
7381 }
7382 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7383 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7384 ALOGV("%s in %p", __func__, in);
7385 ret = -ENOSYS;
7386 goto exit;
7387 }
7388 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7389 if (in->pcm_device_id < 0) {
7390 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7391 __func__, in->pcm_device_id, in->usecase);
7392 ret = -EINVAL;
7393 goto exit;
7394 }
7395
7396 adjust_mmap_period_count(&in->config, min_size_frames);
7397
7398 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7399 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7400 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7401 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307402 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307403 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7404 in->card_status = CARD_STATUS_OFFLINE;
7405 adev->card_status = CARD_STATUS_OFFLINE;
7406 ret = -EIO;
7407 goto exit;
7408 }
7409
Haynes Mathew George16081042017-05-31 17:16:49 -07007410 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7411 step = "open";
7412 ret = -ENODEV;
7413 goto exit;
7414 }
7415
7416 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7417 if (ret < 0) {
7418 step = "begin";
7419 goto exit;
7420 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007421
juyuchen626833d2019-06-04 16:48:02 +08007422 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007423 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7424 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7425 info->burst_size_frames = in->config.period_size;
7426 ret = platform_get_mmap_data_fd(adev->platform,
7427 in->pcm_device_id, 1 /*capture*/,
7428 &info->shared_memory_fd,
7429 &mmap_size);
7430 if (ret < 0) {
7431 // Fall back to non exclusive mode
7432 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7433 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007434 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7435 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7436
Arun Mirpuri5d170872019-03-26 13:21:31 -07007437 if (mmap_size < buffer_size) {
7438 step = "mmap";
7439 goto exit;
7440 }
juyuchen626833d2019-06-04 16:48:02 +08007441 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007442 }
7443
7444 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007445
7446 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7447 if (ret < 0) {
7448 step = "commit";
7449 goto exit;
7450 }
7451
Phil Burke0a86d12019-02-16 22:28:11 -08007452 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7453
Haynes Mathew George16081042017-05-31 17:16:49 -07007454 in->standby = false;
7455 ret = 0;
7456
7457 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7458 __func__, info->shared_memory_address, info->buffer_size_frames);
7459
7460exit:
7461 if (ret != 0) {
7462 if (in->pcm == NULL) {
7463 ALOGE("%s: %s - %d", __func__, step, ret);
7464 } else {
7465 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7466 pcm_close(in->pcm);
7467 in->pcm = NULL;
7468 }
7469 }
7470 pthread_mutex_unlock(&adev->lock);
7471 return ret;
7472}
7473
7474static int in_get_mmap_position(const struct audio_stream_in *stream,
7475 struct audio_mmap_position *position)
7476{
7477 struct stream_in *in = (struct stream_in *)stream;
7478 ALOGVV("%s", __func__);
7479 if (position == NULL) {
7480 return -EINVAL;
7481 }
7482 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7483 return -ENOSYS;
7484 }
7485 if (in->pcm == NULL) {
7486 return -ENOSYS;
7487 }
7488 struct timespec ts = { 0, 0 };
7489 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7490 if (ret < 0) {
7491 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7492 return ret;
7493 }
Phil Burke0a86d12019-02-16 22:28:11 -08007494 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7495 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007496 return 0;
7497}
7498
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307499static int in_get_active_microphones(const struct audio_stream_in *stream,
7500 struct audio_microphone_characteristic_t *mic_array,
7501 size_t *mic_count) {
7502 struct stream_in *in = (struct stream_in *)stream;
7503 struct audio_device *adev = in->dev;
7504 ALOGVV("%s", __func__);
7505
7506 lock_input_stream(in);
7507 pthread_mutex_lock(&adev->lock);
7508 int ret = platform_get_active_microphones(adev->platform,
7509 audio_channel_count_from_in_mask(in->channel_mask),
7510 in->usecase, mic_array, mic_count);
7511 pthread_mutex_unlock(&adev->lock);
7512 pthread_mutex_unlock(&in->lock);
7513
7514 return ret;
7515}
7516
7517static int adev_get_microphones(const struct audio_hw_device *dev,
7518 struct audio_microphone_characteristic_t *mic_array,
7519 size_t *mic_count) {
7520 struct audio_device *adev = (struct audio_device *)dev;
7521 ALOGVV("%s", __func__);
7522
7523 pthread_mutex_lock(&adev->lock);
7524 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7525 pthread_mutex_unlock(&adev->lock);
7526
7527 return ret;
7528}
juyuchendb308c22019-01-21 11:57:17 -07007529
7530static void in_update_sink_metadata(struct audio_stream_in *stream,
7531 const struct sink_metadata *sink_metadata) {
7532
7533 if (stream == NULL
7534 || sink_metadata == NULL
7535 || sink_metadata->tracks == NULL) {
7536 return;
7537 }
7538
7539 int error = 0;
7540 struct stream_in *in = (struct stream_in *)stream;
7541 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007542 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007543 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007544
7545 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007546
7547 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007548 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007549
7550 lock_input_stream(in);
7551 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007552 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007553
Zhou Song62ea0282020-03-22 19:53:01 +08007554 is_ha_usecase = adev->ha_proxy_enable ?
7555 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7556 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7557 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007558 && adev->voice_tx_output != NULL) {
7559 /* Use the rx device from afe-proxy record to route voice call because
7560 there is no routing if tx device is on primary hal and rx device
7561 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007562 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007563
7564 if (!voice_is_call_state_active(adev)) {
7565 if (adev->mode == AUDIO_MODE_IN_CALL) {
7566 adev->current_call_output = adev->voice_tx_output;
7567 error = voice_start_call(adev);
7568 if (error != 0)
7569 ALOGE("%s: start voice call failed %d", __func__, error);
7570 }
7571 } else {
7572 adev->current_call_output = adev->voice_tx_output;
7573 voice_update_devices_for_all_voice_usecases(adev);
7574 }
7575 }
7576
7577 pthread_mutex_unlock(&adev->lock);
7578 pthread_mutex_unlock(&in->lock);
7579}
7580
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307581int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007582 audio_io_handle_t handle,
7583 audio_devices_t devices,
7584 audio_output_flags_t flags,
7585 struct audio_config *config,
7586 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007587 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007588{
7589 struct audio_device *adev = (struct audio_device *)dev;
7590 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307591 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007592 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007593 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307594 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007595 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7596 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7597 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7598 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007599 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007600 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7601 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007602 bool force_haptic_path =
7603 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007604 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007605
kunleizdff872d2018-08-20 14:40:33 +08007606 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007607 is_usb_dev = false;
7608 devices = AUDIO_DEVICE_OUT_SPEAKER;
7609 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7610 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007611 if (config->format == AUDIO_FORMAT_DEFAULT)
7612 config->format = AUDIO_FORMAT_PCM_16_BIT;
7613 if (config->sample_rate == 0)
7614 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7615 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7616 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007617 }
7618
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007619 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307620
Rahul Sharma99770982019-03-06 17:05:26 +05307621 pthread_mutex_lock(&adev->lock);
7622 if (out_get_stream(adev, handle) != NULL) {
7623 ALOGW("%s, output stream already opened", __func__);
7624 ret = -EEXIST;
7625 }
7626 pthread_mutex_unlock(&adev->lock);
7627 if (ret)
7628 return ret;
7629
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007630 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7631
Mingming Yin3a941d42016-02-17 18:08:05 -08007632 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007633 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7634 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307635
7636
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007637 if (!out) {
7638 return -ENOMEM;
7639 }
7640
Haynes Mathew George204045b2015-02-25 20:32:03 -08007641 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007642 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307643 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007644 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007645 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007647 if (devices == AUDIO_DEVICE_NONE)
7648 devices = AUDIO_DEVICE_OUT_SPEAKER;
7649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007650 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007651 list_init(&out->device_list);
7652 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007653 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007654 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007655 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307656 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307657 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7658 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7659 else
7660 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007661 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007662 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007663 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307664 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307665 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307666 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007667 out->hal_output_suspend_supported = 0;
7668 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307669 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307670 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307671 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007672 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007673
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307674 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307675 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007676 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7677
Aalique Grahame22e49102018-12-18 14:23:57 -08007678 if (direct_dev &&
7679 (audio_is_linear_pcm(out->format) ||
7680 config->format == AUDIO_FORMAT_DEFAULT) &&
7681 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7682 audio_format_t req_format = config->format;
7683 audio_channel_mask_t req_channel_mask = config->channel_mask;
7684 uint32_t req_sample_rate = config->sample_rate;
7685
7686 pthread_mutex_lock(&adev->lock);
7687 if (is_hdmi) {
7688 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7689 ret = read_hdmi_sink_caps(out);
7690 if (config->sample_rate == 0)
7691 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7692 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7693 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7694 if (config->format == AUDIO_FORMAT_DEFAULT)
7695 config->format = AUDIO_FORMAT_PCM_16_BIT;
7696 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007697 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7698 &config->format,
7699 &out->supported_formats[0],
7700 MAX_SUPPORTED_FORMATS,
7701 &config->channel_mask,
7702 &out->supported_channel_masks[0],
7703 MAX_SUPPORTED_CHANNEL_MASKS,
7704 &config->sample_rate,
7705 &out->supported_sample_rates[0],
7706 MAX_SUPPORTED_SAMPLE_RATES);
7707 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007708 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007709
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007710 pthread_mutex_unlock(&adev->lock);
7711 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007712 if (ret == -ENOSYS) {
7713 /* ignore and go with default */
7714 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007715 }
7716 // For MMAP NO IRQ, allow conversions in ADSP
7717 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7718 goto error_open;
7719 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007720 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007721 goto error_open;
7722 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007723
7724 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7725 config->sample_rate = req_sample_rate;
7726 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7727 config->channel_mask = req_channel_mask;
7728 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7729 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007730 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007731
7732 out->sample_rate = config->sample_rate;
7733 out->channel_mask = config->channel_mask;
7734 out->format = config->format;
7735 if (is_hdmi) {
7736 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7737 out->config = pcm_config_hdmi_multi;
7738 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7739 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7740 out->config = pcm_config_mmap_playback;
7741 out->stream.start = out_start;
7742 out->stream.stop = out_stop;
7743 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7744 out->stream.get_mmap_position = out_get_mmap_position;
7745 } else {
7746 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7747 out->config = pcm_config_hifi;
7748 }
7749
7750 out->config.rate = out->sample_rate;
7751 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7752 if (is_hdmi) {
7753 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7754 audio_bytes_per_sample(out->format));
7755 }
7756 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007757 }
7758
Derek Chenf6318be2017-06-12 17:16:24 -04007759 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007760 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007761 /* extract car audio stream index */
7762 out->car_audio_stream =
7763 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7764 if (out->car_audio_stream < 0) {
7765 ALOGE("%s: invalid car audio stream %x",
7766 __func__, out->car_audio_stream);
7767 ret = -EINVAL;
7768 goto error_open;
7769 }
Derek Chen5f67a942020-02-24 23:08:13 -08007770 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007771 }
7772
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007773 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007774 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007775 if (!voice_extn_is_compress_voip_supported()) {
7776 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7777 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007778 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7779 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007780 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7781 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007782 out->volume_l = INVALID_OUT_VOLUME;
7783 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007784
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007785 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007786 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007787 uint32_t channel_count =
7788 audio_channel_count_from_out_mask(out->channel_mask);
7789 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7790 out->sample_rate, out->format,
7791 channel_count, false);
7792 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7793 if (frame_size != 0)
7794 out->config.period_size = buffer_size / frame_size;
7795 else
7796 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007797 }
7798 } else {
7799 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7800 voice_extn_compress_voip_is_active(out->dev)) &&
7801 (voice_extn_compress_voip_is_config_supported(config))) {
7802 ret = voice_extn_compress_voip_open_output_stream(out);
7803 if (ret != 0) {
7804 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7805 __func__, ret);
7806 goto error_open;
7807 }
Sujin Panicker19027262019-09-16 18:28:06 +05307808 } else {
7809 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7810 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007811 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007812 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007813 } else if (audio_is_linear_pcm(out->format) &&
7814 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7815 out->channel_mask = config->channel_mask;
7816 out->sample_rate = config->sample_rate;
7817 out->format = config->format;
7818 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7819 // does this change?
7820 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7821 out->config.rate = config->sample_rate;
7822 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7823 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7824 audio_bytes_per_sample(config->format));
7825 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007826 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307827 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307828 pthread_mutex_lock(&adev->lock);
7829 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7830 pthread_mutex_unlock(&adev->lock);
7831
7832 // reject offload during card offline to allow
7833 // fallback to s/w paths
7834 if (offline) {
7835 ret = -ENODEV;
7836 goto error_open;
7837 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007838
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007839 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7840 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7841 ALOGE("%s: Unsupported Offload information", __func__);
7842 ret = -EINVAL;
7843 goto error_open;
7844 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007845
Atul Khare3fa6e542017-08-09 00:56:17 +05307846 if (config->offload_info.format == 0)
7847 config->offload_info.format = config->format;
7848 if (config->offload_info.sample_rate == 0)
7849 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007850
Mingming Yin90310102013-11-13 16:57:00 -08007851 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307852 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007853 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007854 ret = -EINVAL;
7855 goto error_open;
7856 }
7857
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007858 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7859 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7860 (audio_extn_passthru_is_passthrough_stream(out)) &&
7861 !((config->sample_rate == 48000) ||
7862 (config->sample_rate == 96000) ||
7863 (config->sample_rate == 192000))) {
7864 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7865 __func__, config->sample_rate, config->offload_info.format);
7866 ret = -EINVAL;
7867 goto error_open;
7868 }
7869
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007870 out->compr_config.codec = (struct snd_codec *)
7871 calloc(1, sizeof(struct snd_codec));
7872
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007873 if (!out->compr_config.codec) {
7874 ret = -ENOMEM;
7875 goto error_open;
7876 }
7877
Dhananjay Kumarac341582017-02-23 23:42:25 +05307878 out->stream.pause = out_pause;
7879 out->stream.resume = out_resume;
7880 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307881 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307882 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007883 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307884 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007885 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307886 } else {
7887 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7888 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007889 }
vivek mehta446c3962015-09-14 10:57:35 -07007890
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307891 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7892 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007893#ifdef AUDIO_GKI_ENABLED
7894 /* out->compr_config.codec->reserved[1] is for flags */
7895 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7896#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307897 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007898#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307899 }
7900
vivek mehta446c3962015-09-14 10:57:35 -07007901 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007902 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007903 config->format == 0 && config->sample_rate == 0 &&
7904 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007905 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007906 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7907 } else {
7908 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7909 ret = -EEXIST;
7910 goto error_open;
7911 }
vivek mehta446c3962015-09-14 10:57:35 -07007912 }
7913
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007914 if (config->offload_info.channel_mask)
7915 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007916 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007917 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007918 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007919 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307920 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007921 ret = -EINVAL;
7922 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007923 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007924
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007925 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007926 out->sample_rate = config->offload_info.sample_rate;
7927
Mingming Yin3ee55c62014-08-04 14:23:35 -07007928 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007929
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307930 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307931 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307932 audio_extn_dolby_send_ddp_endp_params(adev);
7933 audio_extn_dolby_set_dmid(adev);
7934 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007935
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007936 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007937 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007938 out->compr_config.codec->bit_rate =
7939 config->offload_info.bit_rate;
7940 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307941 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007942 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307943 /* Update bit width only for non passthrough usecases.
7944 * For passthrough usecases, the output will always be opened @16 bit
7945 */
7946 if (!audio_extn_passthru_is_passthrough_stream(out))
7947 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307948
7949 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007950#ifdef AUDIO_GKI_ENABLED
7951 /* out->compr_config.codec->reserved[1] is for flags */
7952 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7953 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7954#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307955 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7956 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007957#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307958
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007959 /*TODO: Do we need to change it for passthrough */
7960 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007961
Manish Dewangana6fc5442015-08-24 20:30:31 +05307962 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7963 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307964 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307965 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307966 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7967 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307968
7969 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7970 AUDIO_FORMAT_PCM) {
7971
7972 /*Based on platform support, configure appropriate alsa format for corresponding
7973 *hal input format.
7974 */
7975 out->compr_config.codec->format = hal_format_to_alsa(
7976 config->offload_info.format);
7977
Ashish Jain83a6cc22016-06-28 14:34:17 +05307978 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307979 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307980 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307981
Dhananjay Kumarac341582017-02-23 23:42:25 +05307982 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307983 *hal input format and alsa format might differ based on platform support.
7984 */
7985 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307986 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307987
7988 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7989
Deeraj Soman93155a62019-09-30 19:00:37 +05307990 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7991 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7992 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7993 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7994 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307995
Ashish Jainf1eaa582016-05-23 20:54:24 +05307996 /* Check if alsa session is configured with the same format as HAL input format,
7997 * if not then derive correct fragment size needed to accomodate the
7998 * conversion of HAL input format to alsa format.
7999 */
8000 audio_extn_utils_update_direct_pcm_fragment_size(out);
8001
8002 /*if hal input and output fragment size is different this indicates HAL input format is
8003 *not same as the alsa format
8004 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308005 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308006 /*Allocate a buffer to convert input data to the alsa configured format.
8007 *size of convert buffer is equal to the size required to hold one fragment size
8008 *worth of pcm data, this is because flinger does not write more than fragment_size
8009 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308010 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8011 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308012 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8013 ret = -ENOMEM;
8014 goto error_open;
8015 }
8016 }
8017 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8018 out->compr_config.fragment_size =
8019 audio_extn_passthru_get_buffer_size(&config->offload_info);
8020 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8021 } else {
8022 out->compr_config.fragment_size =
8023 platform_get_compress_offload_buffer_size(&config->offload_info);
8024 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8025 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008026
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308027 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8028 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8029 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07008030 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308031 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008032
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308033 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8034 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8035 }
8036
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008037 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8038 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008039
Manish Dewangan69426c82017-01-30 17:35:36 +05308040 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8041 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8042 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8043 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8044 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8045 } else {
8046 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8047 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008048
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308049 memset(&out->channel_map_param, 0,
8050 sizeof(struct audio_out_channel_map_param));
8051
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008052 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308053 out->send_next_track_params = false;
8054 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008055 out->offload_state = OFFLOAD_STATE_IDLE;
8056 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008057 out->writeAt.tv_sec = 0;
8058 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008059
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008060 audio_extn_dts_create_state_notifier_node(out->usecase);
8061
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008062 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8063 __func__, config->offload_info.version,
8064 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308065
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308066 /* Check if DSD audio format is supported in codec
8067 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308068 */
8069
8070 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308071 (!platform_check_codec_dsd_support(adev->platform) ||
8072 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308073 ret = -EINVAL;
8074 goto error_open;
8075 }
8076
Ashish Jain5106d362016-05-11 19:23:33 +05308077 /* Disable gapless if any of the following is true
8078 * passthrough playback
8079 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308080 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308081 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308082 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308083 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008084 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308085 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308086 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308087 check_and_set_gapless_mode(adev, false);
8088 } else
8089 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008090
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308091 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008092 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8093 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308094 if (config->format == AUDIO_FORMAT_DSD) {
8095 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008096#ifdef AUDIO_GKI_ENABLED
8097 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8098 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8099#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308100 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008101#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308102 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008103
8104 create_offload_callback_thread(out);
8105
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008106 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008107 switch (config->sample_rate) {
8108 case 0:
8109 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8110 break;
8111 case 8000:
8112 case 16000:
8113 case 48000:
8114 out->sample_rate = config->sample_rate;
8115 break;
8116 default:
8117 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8118 config->sample_rate);
8119 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8120 ret = -EINVAL;
8121 goto error_open;
8122 }
8123 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8124 switch (config->channel_mask) {
8125 case AUDIO_CHANNEL_NONE:
8126 case AUDIO_CHANNEL_OUT_STEREO:
8127 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8128 break;
8129 default:
8130 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8131 config->channel_mask);
8132 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8133 ret = -EINVAL;
8134 goto error_open;
8135 }
8136 switch (config->format) {
8137 case AUDIO_FORMAT_DEFAULT:
8138 case AUDIO_FORMAT_PCM_16_BIT:
8139 out->format = AUDIO_FORMAT_PCM_16_BIT;
8140 break;
8141 default:
8142 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8143 config->format);
8144 config->format = AUDIO_FORMAT_PCM_16_BIT;
8145 ret = -EINVAL;
8146 goto error_open;
8147 }
8148
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308149 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008150 if (ret != 0) {
8151 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008152 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008153 goto error_open;
8154 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008155 } else if (is_single_device_type_equal(&out->device_list,
8156 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008157 switch (config->sample_rate) {
8158 case 0:
8159 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8160 break;
8161 case 8000:
8162 case 16000:
8163 case 48000:
8164 out->sample_rate = config->sample_rate;
8165 break;
8166 default:
8167 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8168 config->sample_rate);
8169 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8170 ret = -EINVAL;
8171 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008172 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008173 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8174 switch (config->channel_mask) {
8175 case AUDIO_CHANNEL_NONE:
8176 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8177 break;
8178 case AUDIO_CHANNEL_OUT_STEREO:
8179 out->channel_mask = config->channel_mask;
8180 break;
8181 default:
8182 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8183 config->channel_mask);
8184 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8185 ret = -EINVAL;
8186 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008187 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008188 switch (config->format) {
8189 case AUDIO_FORMAT_DEFAULT:
8190 out->format = AUDIO_FORMAT_PCM_16_BIT;
8191 break;
8192 case AUDIO_FORMAT_PCM_16_BIT:
8193 out->format = config->format;
8194 break;
8195 default:
8196 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8197 config->format);
8198 config->format = AUDIO_FORMAT_PCM_16_BIT;
8199 ret = -EINVAL;
8200 break;
8201 }
8202 if (ret != 0)
8203 goto error_open;
8204
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008205 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8206 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008207 out->config.rate = out->sample_rate;
8208 out->config.channels =
8209 audio_channel_count_from_out_mask(out->channel_mask);
8210 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008211 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008212 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308213 unsigned int channels = 0;
8214 /*Update config params to default if not set by the caller*/
8215 if (config->sample_rate == 0)
8216 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8217 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8218 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8219 if (config->format == AUDIO_FORMAT_DEFAULT)
8220 config->format = AUDIO_FORMAT_PCM_16_BIT;
8221
8222 channels = audio_channel_count_from_out_mask(out->channel_mask);
8223
Varun Balaraje49253e2017-07-06 19:48:56 +05308224 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8225 out->usecase = get_interactive_usecase(adev);
8226 out->config = pcm_config_low_latency;
8227 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308228 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008229 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8230 out->flags);
8231 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008232 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8233 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8234 out->config = pcm_config_mmap_playback;
8235 out->stream.start = out_start;
8236 out->stream.stop = out_stop;
8237 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8238 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308239 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8240 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008241 out->hal_output_suspend_supported =
8242 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8243 out->dynamic_pm_qos_config_supported =
8244 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8245 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008246 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8247 } else {
8248 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8249 //the mixer path will be a string similar to "low-latency-playback resume"
8250 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8251 strlcat(out->pm_qos_mixer_path,
8252 " resume", MAX_MIXER_PATH_LEN);
8253 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8254 out->pm_qos_mixer_path);
8255 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308256 out->config = pcm_config_low_latency;
8257 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8258 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8259 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308260 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8261 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8262 if (out->config.period_size <= 0) {
8263 ALOGE("Invalid configuration period size is not valid");
8264 ret = -EINVAL;
8265 goto error_open;
8266 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008267 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8268 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8269 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008270 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8271 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8272 out->config = pcm_config_haptics_audio;
8273 if (force_haptic_path)
8274 adev->haptics_config = pcm_config_haptics_audio;
8275 else
8276 adev->haptics_config = pcm_config_haptics;
8277
Meng Wangd08ce322020-04-02 08:59:20 +08008278 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008279 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8280
8281 if (force_haptic_path) {
8282 out->config.channels = 1;
8283 adev->haptics_config.channels = 1;
8284 } else
8285 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 -08008286 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008287 ret = audio_extn_auto_hal_open_output_stream(out);
8288 if (ret) {
8289 ALOGE("%s: Failed to open output stream for bus device", __func__);
8290 ret = -EINVAL;
8291 goto error_open;
8292 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308293 } else {
8294 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008295 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8296 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308297 }
8298 out->hal_ip_format = format = out->format;
8299 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8300 out->hal_op_format = pcm_format_to_hal(out->config.format);
8301 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8302 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008303 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308304 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308305 if (out->hal_ip_format != out->hal_op_format) {
8306 uint32_t buffer_size = out->config.period_size *
8307 format_to_bitwidth_table[out->hal_op_format] *
8308 out->config.channels;
8309 out->convert_buffer = calloc(1, buffer_size);
8310 if (out->convert_buffer == NULL){
8311 ALOGE("Allocation failed for convert buffer for size %d",
8312 out->compr_config.fragment_size);
8313 ret = -ENOMEM;
8314 goto error_open;
8315 }
8316 ALOGD("Convert buffer allocated of size %d", buffer_size);
8317 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008318 }
8319
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008320 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8321 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308322
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008323 /* TODO remove this hardcoding and check why width is zero*/
8324 if (out->bit_width == 0)
8325 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308326 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008327 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008328 &out->device_list, out->flags,
8329 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308330 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308331 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008332 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008333 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8334 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008335 if(adev->primary_output == NULL)
8336 adev->primary_output = out;
8337 else {
8338 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008339 ret = -EEXIST;
8340 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008341 }
8342 }
8343
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008344 /* Check if this usecase is already existing */
8345 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008346 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8347 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008348 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008349 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008350 ret = -EEXIST;
8351 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008352 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008354 pthread_mutex_unlock(&adev->lock);
8355
8356 out->stream.common.get_sample_rate = out_get_sample_rate;
8357 out->stream.common.set_sample_rate = out_set_sample_rate;
8358 out->stream.common.get_buffer_size = out_get_buffer_size;
8359 out->stream.common.get_channels = out_get_channels;
8360 out->stream.common.get_format = out_get_format;
8361 out->stream.common.set_format = out_set_format;
8362 out->stream.common.standby = out_standby;
8363 out->stream.common.dump = out_dump;
8364 out->stream.common.set_parameters = out_set_parameters;
8365 out->stream.common.get_parameters = out_get_parameters;
8366 out->stream.common.add_audio_effect = out_add_audio_effect;
8367 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8368 out->stream.get_latency = out_get_latency;
8369 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008370#ifdef NO_AUDIO_OUT
8371 out->stream.write = out_write_for_no_output;
8372#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008373 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008374#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008375 out->stream.get_render_position = out_get_render_position;
8376 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008377 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008378
Haynes Mathew George16081042017-05-31 17:16:49 -07008379 if (out->realtime)
8380 out->af_period_multiplier = af_period_multiplier;
8381 else
8382 out->af_period_multiplier = 1;
8383
Andy Hunga1f48fa2019-07-01 18:14:53 -07008384 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008386 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008387 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008388 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008389
8390 config->format = out->stream.common.get_format(&out->stream.common);
8391 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8392 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308393 register_format(out->format, out->supported_formats);
8394 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8395 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008396
Aalique Grahame22e49102018-12-18 14:23:57 -08008397 out->error_log = error_log_create(
8398 ERROR_LOG_ENTRIES,
8399 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8400
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308401 /*
8402 By locking output stream before registering, we allow the callback
8403 to update stream's state only after stream's initial state is set to
8404 adev state.
8405 */
8406 lock_output_stream(out);
8407 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8408 pthread_mutex_lock(&adev->lock);
8409 out->card_status = adev->card_status;
8410 pthread_mutex_unlock(&adev->lock);
8411 pthread_mutex_unlock(&out->lock);
8412
Aalique Grahame22e49102018-12-18 14:23:57 -08008413 stream_app_type_cfg_init(&out->app_type_cfg);
8414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008415 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308416 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008417 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008418
8419 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8420 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8421 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008422 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308423 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008424 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008425 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308426 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8427 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008428 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8429 out->usecase, PCM_PLAYBACK);
8430 hdlr_stream_cfg.flags = out->flags;
8431 hdlr_stream_cfg.type = PCM_PLAYBACK;
8432 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8433 &hdlr_stream_cfg);
8434 if (ret) {
8435 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8436 out->adsp_hdlr_stream_handle = NULL;
8437 }
8438 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308439 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8440 is_direct_passthough, false);
8441 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8442 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008443 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008444 if (ret < 0) {
8445 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8446 out->ip_hdlr_handle = NULL;
8447 }
8448 }
Derek Chenf939fb72018-11-13 13:34:41 -08008449
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008450 ret = io_streams_map_insert(adev, &out->stream.common,
8451 out->handle, AUDIO_PATCH_HANDLE_NONE);
8452 if (ret != 0)
8453 goto error_open;
8454
Derek Chenf939fb72018-11-13 13:34:41 -08008455 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8456 calloc(1, sizeof(streams_output_ctxt_t));
8457 if (out_ctxt == NULL) {
8458 ALOGE("%s fail to allocate output ctxt", __func__);
8459 ret = -ENOMEM;
8460 goto error_open;
8461 }
8462 out_ctxt->output = out;
8463
8464 pthread_mutex_lock(&adev->lock);
8465 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8466 pthread_mutex_unlock(&adev->lock);
8467
Eric Laurent994a6932013-07-17 11:51:42 -07008468 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008469 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008470
8471error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308472 if (out->convert_buffer)
8473 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008474 free(out);
8475 *stream_out = NULL;
8476 ALOGD("%s: exit: ret %d", __func__, ret);
8477 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008478}
8479
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308480void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008481 struct audio_stream_out *stream)
8482{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008483 struct stream_out *out = (struct stream_out *)stream;
8484 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008485 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008486
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008487 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308488
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008489 io_streams_map_remove(adev, out->handle);
8490
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308491 // must deregister from sndmonitor first to prevent races
8492 // between the callback and close_stream
8493 audio_extn_snd_mon_unregister_listener(out);
8494
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008495 /* close adsp hdrl session before standby */
8496 if (out->adsp_hdlr_stream_handle) {
8497 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8498 if (ret)
8499 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8500 out->adsp_hdlr_stream_handle = NULL;
8501 }
8502
Manish Dewangan21a850a2017-08-14 12:03:55 +05308503 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008504 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8505 out->ip_hdlr_handle = NULL;
8506 }
8507
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008508 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308509 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008510 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308511 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308512 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008513 if(ret != 0)
8514 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8515 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008516 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008517 out_standby(&stream->common);
8518
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008519 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008520 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008521 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008522 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008523 if (out->compr_config.codec != NULL)
8524 free(out->compr_config.codec);
8525 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008526
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308527 out->a2dp_compress_mute = false;
8528
Varun Balaraje49253e2017-07-06 19:48:56 +05308529 if (is_interactive_usecase(out->usecase))
8530 free_interactive_usecase(adev, out->usecase);
8531
Ashish Jain83a6cc22016-06-28 14:34:17 +05308532 if (out->convert_buffer != NULL) {
8533 free(out->convert_buffer);
8534 out->convert_buffer = NULL;
8535 }
8536
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008537 if (adev->voice_tx_output == out)
8538 adev->voice_tx_output = NULL;
8539
Aalique Grahame22e49102018-12-18 14:23:57 -08008540 error_log_destroy(out->error_log);
8541 out->error_log = NULL;
8542
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308543 if (adev->primary_output == out)
8544 adev->primary_output = NULL;
8545
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008546 pthread_cond_destroy(&out->cond);
8547 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008548
8549 pthread_mutex_lock(&adev->lock);
8550 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8551 if (out_ctxt != NULL) {
8552 list_remove(&out_ctxt->list);
8553 free(out_ctxt);
8554 } else {
8555 ALOGW("%s, output stream already closed", __func__);
8556 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008557 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008558 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008559 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008560}
8561
8562static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8563{
8564 struct audio_device *adev = (struct audio_device *)dev;
8565 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008566 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008567 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008568 int ret;
8569 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008570 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008571 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008572 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008573
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008574 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008575 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008576
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308577 if (!parms)
8578 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308579
Derek Chen6f293672019-04-01 01:40:24 -07008580 /* notify adev and input/output streams on the snd card status */
8581 adev_snd_mon_cb((void *)adev, parms);
8582
8583 list_for_each(node, &adev->active_outputs_list) {
8584 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8585 streams_output_ctxt_t,
8586 list);
8587 out_snd_mon_cb((void *)out_ctxt->output, parms);
8588 }
8589
8590 list_for_each(node, &adev->active_inputs_list) {
8591 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8592 streams_input_ctxt_t,
8593 list);
8594 in_snd_mon_cb((void *)in_ctxt->input, parms);
8595 }
8596
Zhou Songd6d71752019-05-21 18:08:51 +08008597 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308598 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8599 if (ret >= 0) {
8600 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008601 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308602 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008603 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308604 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008605 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008606 }
8607 }
8608
8609 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8610 if (ret>=0) {
8611 if (!strncmp(value, "false", 5) &&
8612 audio_extn_a2dp_source_is_suspended()) {
8613 struct audio_usecase *usecase;
8614 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008615 list_for_each(node, &adev->usecase_list) {
8616 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008617 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008618 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008619 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008620 reassign_device_list(&usecase->stream.in->device_list,
8621 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008622 select_devices(adev, usecase->id);
8623 }
Zhou Songd6d71752019-05-21 18:08:51 +08008624 }
8625 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308626 }
8627
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008628 status = voice_set_parameters(adev, parms);
8629 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008630 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008631
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008632 status = platform_set_parameters(adev->platform, parms);
8633 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008634 goto done;
8635
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008636 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8637 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008638 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008639 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8640 adev->bluetooth_nrec = true;
8641 else
8642 adev->bluetooth_nrec = false;
8643 }
8644
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008645 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8646 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008647 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8648 adev->screen_off = false;
8649 else
8650 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008651 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008652 }
8653
Eric Laurent4b084132018-10-19 17:33:43 -07008654 ret = str_parms_get_int(parms, "rotation", &val);
8655 if (ret >= 0) {
8656 bool reverse_speakers = false;
8657 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8658 switch (val) {
8659 // FIXME: note that the code below assumes that the speakers are in the correct placement
8660 // relative to the user when the device is rotated 90deg from its default rotation. This
8661 // assumption is device-specific, not platform-specific like this code.
8662 case 270:
8663 reverse_speakers = true;
8664 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8665 break;
8666 case 0:
8667 case 180:
8668 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8669 break;
8670 case 90:
8671 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8672 break;
8673 default:
8674 ALOGE("%s: unexpected rotation of %d", __func__, val);
8675 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008676 }
Eric Laurent4b084132018-10-19 17:33:43 -07008677 if (status == 0) {
8678 // check and set swap
8679 // - check if orientation changed and speaker active
8680 // - set rotation and cache the rotation value
8681 adev->camera_orientation =
8682 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8683 if (!audio_extn_is_maxx_audio_enabled())
8684 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8685 }
8686 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008687
Mingming Yin514a8bc2014-07-29 15:22:21 -07008688 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8689 if (ret >= 0) {
8690 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8691 adev->bt_wb_speech_enabled = true;
8692 else
8693 adev->bt_wb_speech_enabled = false;
8694 }
8695
Zhou Song12c29502019-03-16 10:37:18 +08008696 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8697 if (ret >= 0) {
8698 val = atoi(value);
8699 adev->swb_speech_mode = val;
8700 }
8701
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008702 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8703 if (ret >= 0) {
8704 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308705 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008706 if (audio_is_output_device(val) &&
8707 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008708 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008709 platform_get_controller_stream_from_params(parms, &controller, &stream);
8710 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8711 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008712 if (ret < 0) {
8713 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308714 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008715 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008716 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308717 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008718 /*
8719 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8720 * Per AudioPolicyManager, USB device is higher priority than WFD.
8721 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8722 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8723 * starting voice call on USB
8724 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008725 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308726 if (ret >= 0)
8727 audio_extn_usb_add_device(device, atoi(value));
8728
Zhou Song6f862822017-11-06 17:27:57 +08008729 if (!audio_extn_usb_is_tunnel_supported()) {
8730 ALOGV("detected USB connect .. disable proxy");
8731 adev->allow_afe_proxy_usage = false;
8732 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008733 }
8734 }
8735
8736 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8737 if (ret >= 0) {
8738 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308739 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008740 /*
8741 * The HDMI / Displayport disconnect handling has been moved to
8742 * audio extension to ensure that its parameters are not
8743 * invalidated prior to updating sysfs of the disconnect event
8744 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8745 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308746 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008747 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308748 if (ret >= 0)
8749 audio_extn_usb_remove_device(device, atoi(value));
8750
Zhou Song6f862822017-11-06 17:27:57 +08008751 if (!audio_extn_usb_is_tunnel_supported()) {
8752 ALOGV("detected USB disconnect .. enable proxy");
8753 adev->allow_afe_proxy_usage = true;
8754 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008755 }
8756 }
8757
Aalique Grahame22e49102018-12-18 14:23:57 -08008758 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008759 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008760
8761 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008762 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308763 struct audio_usecase *usecase;
8764 struct listnode *node;
8765 list_for_each(node, &adev->usecase_list) {
8766 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308767 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008768 is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308769 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008770 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308771 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008772 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308773 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308774 ALOGD("Switching to speaker and muting the stream before select_devices");
8775 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308776 //force device switch to re configure encoder
8777 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308778 ALOGD("Unmuting the stream after select_devices");
8779 usecase->stream.out->a2dp_compress_mute = false;
8780 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 +05308781 audio_extn_a2dp_set_handoff_mode(false);
8782 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308783 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308784 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8785 usecase->stream.out->a2dp_compress_mute) {
8786 pthread_mutex_unlock(&adev->lock);
8787 lock_output_stream(usecase->stream.out);
8788 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008789 reassign_device_list(&usecase->stream.out->device_list,
8790 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308791 check_a2dp_restore_l(adev, usecase->stream.out, true);
8792 pthread_mutex_unlock(&usecase->stream.out->lock);
8793 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308794 }
8795 }
8796 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008797
8798 //handle vr audio setparam
8799 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8800 value, sizeof(value));
8801 if (ret >= 0) {
8802 ALOGI("Setting vr mode to be %s", value);
8803 if (!strncmp(value, "true", 4)) {
8804 adev->vr_audio_mode_enabled = true;
8805 ALOGI("Setting vr mode to true");
8806 } else if (!strncmp(value, "false", 5)) {
8807 adev->vr_audio_mode_enabled = false;
8808 ALOGI("Setting vr mode to false");
8809 } else {
8810 ALOGI("wrong vr mode set");
8811 }
8812 }
8813
Eric Laurent4b084132018-10-19 17:33:43 -07008814 //FIXME: to be replaced by proper video capture properties API
8815 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8816 if (ret >= 0) {
8817 int camera_facing = CAMERA_FACING_BACK;
8818 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8819 camera_facing = CAMERA_FACING_FRONT;
8820 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8821 camera_facing = CAMERA_FACING_BACK;
8822 else {
8823 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8824 goto done;
8825 }
8826 adev->camera_orientation =
8827 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8828 struct audio_usecase *usecase;
8829 struct listnode *node;
8830 list_for_each(node, &adev->usecase_list) {
8831 usecase = node_to_item(node, struct audio_usecase, list);
8832 struct stream_in *in = usecase->stream.in;
8833 if (usecase->type == PCM_CAPTURE && in != NULL &&
8834 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8835 select_devices(adev, in->usecase);
8836 }
8837 }
8838 }
8839
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308840 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008841done:
8842 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008843 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308844error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008845 ALOGV("%s: exit with code(%d)", __func__, status);
8846 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008847}
8848
8849static char* adev_get_parameters(const struct audio_hw_device *dev,
8850 const char *keys)
8851{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308852 ALOGD("%s:%s", __func__, keys);
8853
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008854 struct audio_device *adev = (struct audio_device *)dev;
8855 struct str_parms *reply = str_parms_create();
8856 struct str_parms *query = str_parms_create_str(keys);
8857 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308858 char value[256] = {0};
8859 int ret = 0;
8860
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008861 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008862 if (reply) {
8863 str_parms_destroy(reply);
8864 }
8865 if (query) {
8866 str_parms_destroy(query);
8867 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008868 ALOGE("adev_get_parameters: failed to create query or reply");
8869 return NULL;
8870 }
8871
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008872 //handle vr audio getparam
8873
8874 ret = str_parms_get_str(query,
8875 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8876 value, sizeof(value));
8877
8878 if (ret >= 0) {
8879 bool vr_audio_enabled = false;
8880 pthread_mutex_lock(&adev->lock);
8881 vr_audio_enabled = adev->vr_audio_mode_enabled;
8882 pthread_mutex_unlock(&adev->lock);
8883
8884 ALOGI("getting vr mode to %d", vr_audio_enabled);
8885
8886 if (vr_audio_enabled) {
8887 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8888 "true");
8889 goto exit;
8890 } else {
8891 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8892 "false");
8893 goto exit;
8894 }
8895 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008896
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008897 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008898 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008899 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008900 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008901 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08008902 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308903 pthread_mutex_unlock(&adev->lock);
8904
Naresh Tannirud7205b62014-06-20 02:54:48 +05308905exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008906 str = str_parms_to_str(reply);
8907 str_parms_destroy(query);
8908 str_parms_destroy(reply);
8909
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308910 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008911 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008912}
8913
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008914static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008915{
8916 return 0;
8917}
8918
8919static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8920{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008921 int ret;
8922 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008923
8924 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8925
Haynes Mathew George5191a852013-09-11 14:19:36 -07008926 pthread_mutex_lock(&adev->lock);
8927 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008928 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008929 pthread_mutex_unlock(&adev->lock);
8930 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008931}
8932
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008933static int adev_set_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_get_master_volume(struct audio_hw_device *dev __unused,
8940 float *volume __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_set_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
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008951static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8952 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008953{
8954 return -ENOSYS;
8955}
8956
8957static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8958{
8959 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008960 struct listnode *node;
8961 struct audio_usecase *usecase = NULL;
8962 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008964 pthread_mutex_lock(&adev->lock);
8965 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05308966 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
8967 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008968 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05308969 if( mode == AUDIO_MODE_CALL_SCREEN ){
8970 adev->current_call_output = adev->primary_output;
8971 voice_start_call(adev);
8972 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008973 (mode == AUDIO_MODE_NORMAL ||
8974 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008975 list_for_each(node, &adev->usecase_list) {
8976 usecase = node_to_item(node, struct audio_usecase, list);
8977 if (usecase->type == VOICE_CALL)
8978 break;
8979 }
8980 if (usecase &&
8981 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8982 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8983 true);
8984 if (ret != 0) {
8985 /* default service interval was successfully updated,
8986 reopen USB backend with new service interval */
8987 check_usecases_codec_backend(adev,
8988 usecase,
8989 usecase->out_snd_device);
8990 }
8991 }
8992
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008993 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008994 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008995 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008996 // restore device for other active usecases after stop call
8997 list_for_each(node, &adev->usecase_list) {
8998 usecase = node_to_item(node, struct audio_usecase, list);
8999 select_devices(adev, usecase->id);
9000 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009001 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009002 }
9003 pthread_mutex_unlock(&adev->lock);
9004 return 0;
9005}
9006
9007static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9008{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009009 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009010 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009011
9012 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009013 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009014 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009015
Derek Chend2530072014-11-24 12:39:14 -08009016 if (adev->ext_hw_plugin)
9017 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009018
9019 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009020 pthread_mutex_unlock(&adev->lock);
9021
9022 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009023}
9024
9025static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9026{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009027 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009028 return 0;
9029}
9030
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009031static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009032 const struct audio_config *config)
9033{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009034 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009035
Aalique Grahame22e49102018-12-18 14:23:57 -08009036 /* Don't know if USB HIFI in this context so use true to be conservative */
9037 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9038 true /*is_usb_hifi */) != 0)
9039 return 0;
9040
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009041 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9042 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009043}
9044
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009045static bool adev_input_allow_hifi_record(struct audio_device *adev,
9046 audio_devices_t devices,
9047 audio_input_flags_t flags,
9048 audio_source_t source) {
9049 const bool allowed = true;
9050
9051 if (!audio_is_usb_in_device(devices))
9052 return !allowed;
9053
9054 switch (flags) {
9055 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009056 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009057 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9058 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009059 default:
9060 return !allowed;
9061 }
9062
9063 switch (source) {
9064 case AUDIO_SOURCE_DEFAULT:
9065 case AUDIO_SOURCE_MIC:
9066 case AUDIO_SOURCE_UNPROCESSED:
9067 break;
9068 default:
9069 return !allowed;
9070 }
9071
9072 switch (adev->mode) {
9073 case 0:
9074 break;
9075 default:
9076 return !allowed;
9077 }
9078
9079 return allowed;
9080}
9081
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009082static int adev_update_voice_comm_input_stream(struct stream_in *in,
9083 struct audio_config *config)
9084{
9085 bool valid_rate = (config->sample_rate == 8000 ||
9086 config->sample_rate == 16000 ||
9087 config->sample_rate == 32000 ||
9088 config->sample_rate == 48000);
9089 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9090
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009091 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009092 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009093 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9094 in->config = default_pcm_config_voip_copp;
9095 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9096 DEFAULT_VOIP_BUF_DURATION_MS,
9097 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009098 } else {
9099 ALOGW("%s No valid input in voip, use defaults"
9100 "sample rate %u, channel mask 0x%X",
9101 __func__, config->sample_rate, in->channel_mask);
9102 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009103 in->config.rate = config->sample_rate;
9104 in->sample_rate = config->sample_rate;
9105 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009106 //XXX needed for voice_extn_compress_voip_open_input_stream
9107 in->config.rate = config->sample_rate;
9108 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309109 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009110 voice_extn_compress_voip_is_active(in->dev)) &&
9111 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9112 valid_rate && valid_ch) {
9113 voice_extn_compress_voip_open_input_stream(in);
9114 // update rate entries to match config from AF
9115 in->config.rate = config->sample_rate;
9116 in->sample_rate = config->sample_rate;
9117 } else {
9118 ALOGW("%s compress voip not active, use defaults", __func__);
9119 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009120 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009121 return 0;
9122}
9123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009124static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009125 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009126 audio_devices_t devices,
9127 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009128 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309129 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009130 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009131 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009132{
9133 struct audio_device *adev = (struct audio_device *)dev;
9134 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009135 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009136 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009137 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309138 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009139 bool is_usb_dev = audio_is_usb_in_device(devices);
9140 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9141 devices,
9142 flags,
9143 source);
Andy Hung94320602018-10-29 18:31:12 -07009144 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9145 " sample_rate %u, channel_mask %#x, format %#x",
9146 __func__, flags, is_usb_dev, may_use_hifi_record,
9147 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309148
kunleizdff872d2018-08-20 14:40:33 +08009149 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009150 is_usb_dev = false;
9151 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9152 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9153 __func__, devices);
9154 }
9155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009156 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009157
9158 if (!(is_usb_dev && may_use_hifi_record)) {
9159 if (config->sample_rate == 0)
9160 config->sample_rate = 48000;
9161 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9162 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9163 if (config->format == AUDIO_FORMAT_DEFAULT)
9164 config->format = AUDIO_FORMAT_PCM_16_BIT;
9165
9166 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9167
Aalique Grahame22e49102018-12-18 14:23:57 -08009168 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9169 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009170 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309171 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009172
Rahul Sharma99770982019-03-06 17:05:26 +05309173 pthread_mutex_lock(&adev->lock);
9174 if (in_get_stream(adev, handle) != NULL) {
9175 ALOGW("%s, input stream already opened", __func__);
9176 ret = -EEXIST;
9177 }
9178 pthread_mutex_unlock(&adev->lock);
9179 if (ret)
9180 return ret;
9181
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009182 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009183
9184 if (!in) {
9185 ALOGE("failed to allocate input stream");
9186 return -ENOMEM;
9187 }
9188
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309189 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309190 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9191 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009192 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009193 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009195 in->stream.common.get_sample_rate = in_get_sample_rate;
9196 in->stream.common.set_sample_rate = in_set_sample_rate;
9197 in->stream.common.get_buffer_size = in_get_buffer_size;
9198 in->stream.common.get_channels = in_get_channels;
9199 in->stream.common.get_format = in_get_format;
9200 in->stream.common.set_format = in_set_format;
9201 in->stream.common.standby = in_standby;
9202 in->stream.common.dump = in_dump;
9203 in->stream.common.set_parameters = in_set_parameters;
9204 in->stream.common.get_parameters = in_get_parameters;
9205 in->stream.common.add_audio_effect = in_add_audio_effect;
9206 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9207 in->stream.set_gain = in_set_gain;
9208 in->stream.read = in_read;
9209 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009210 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309211 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009212 in->stream.set_microphone_direction = in_set_microphone_direction;
9213 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009214 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009215
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009216 list_init(&in->device_list);
9217 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009218 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009219 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009220 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009221 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009222 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009223 in->bit_width = 16;
9224 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009225 in->direction = MIC_DIRECTION_UNSPECIFIED;
9226 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009227 list_init(&in->aec_list);
9228 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009229 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009230
Andy Hung94320602018-10-29 18:31:12 -07009231 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009232 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9233 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9234 /* Force channel config requested to mono if incall
9235 record is being requested for only uplink/downlink */
9236 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9237 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9238 ret = -EINVAL;
9239 goto err_open;
9240 }
9241 }
9242
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009243 if (is_usb_dev && may_use_hifi_record) {
9244 /* HiFi record selects an appropriate format, channel, rate combo
9245 depending on sink capabilities*/
9246 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9247 &config->format,
9248 &in->supported_formats[0],
9249 MAX_SUPPORTED_FORMATS,
9250 &config->channel_mask,
9251 &in->supported_channel_masks[0],
9252 MAX_SUPPORTED_CHANNEL_MASKS,
9253 &config->sample_rate,
9254 &in->supported_sample_rates[0],
9255 MAX_SUPPORTED_SAMPLE_RATES);
9256 if (ret != 0) {
9257 ret = -EINVAL;
9258 goto err_open;
9259 }
9260 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009261 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309262 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309263 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9264 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9265 in->config.format = PCM_FORMAT_S32_LE;
9266 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309267 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9268 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9269 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9270 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9271 bool ret_error = false;
9272 in->bit_width = 24;
9273 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9274 from HAL is 24_packed and 8_24
9275 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9276 24_packed return error indicating supported format is 24_packed
9277 *> In case of any other source requesting 24 bit or float return error
9278 indicating format supported is 16 bit only.
9279
9280 on error flinger will retry with supported format passed
9281 */
9282 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9283 (source != AUDIO_SOURCE_CAMCORDER)) {
9284 config->format = AUDIO_FORMAT_PCM_16_BIT;
9285 if (config->sample_rate > 48000)
9286 config->sample_rate = 48000;
9287 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009288 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9289 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309290 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9291 ret_error = true;
9292 }
9293
9294 if (ret_error) {
9295 ret = -EINVAL;
9296 goto err_open;
9297 }
9298 }
9299
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009300 in->channel_mask = config->channel_mask;
9301 in->format = config->format;
9302
9303 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309304
9305 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9306 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9307 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9308 else {
9309 ret = -EINVAL;
9310 goto err_open;
9311 }
9312 }
9313
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009314 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309315 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9316 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009317 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9318 is_low_latency = true;
9319#if LOW_LATENCY_CAPTURE_USE_CASE
9320 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9321#endif
9322 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009323 if (!in->realtime) {
9324 in->config = pcm_config_audio_capture;
9325 frame_size = audio_stream_in_frame_size(&in->stream);
9326 buffer_size = get_input_buffer_size(config->sample_rate,
9327 config->format,
9328 channel_count,
9329 is_low_latency);
9330 in->config.period_size = buffer_size / frame_size;
9331 in->config.rate = config->sample_rate;
9332 in->af_period_multiplier = 1;
9333 } else {
9334 // period size is left untouched for rt mode playback
9335 in->config = pcm_config_audio_capture_rt;
9336 in->af_period_multiplier = af_period_multiplier;
9337 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009338 }
9339
9340 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9341 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9342 in->realtime = 0;
9343 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9344 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009345 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009346 in->stream.start = in_start;
9347 in->stream.stop = in_stop;
9348 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9349 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009350 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009351 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009352 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9353 in->config = pcm_config_audio_capture;
9354 frame_size = audio_stream_in_frame_size(&in->stream);
9355 buffer_size = get_input_buffer_size(config->sample_rate,
9356 config->format,
9357 channel_count,
9358 false /*is_low_latency*/);
9359 in->config.period_size = buffer_size / frame_size;
9360 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009361 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009362 switch (config->format) {
9363 case AUDIO_FORMAT_PCM_32_BIT:
9364 in->bit_width = 32;
9365 break;
9366 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9367 case AUDIO_FORMAT_PCM_8_24_BIT:
9368 in->bit_width = 24;
9369 break;
9370 default:
9371 in->bit_width = 16;
9372 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009373 } else if (is_single_device_type_equal(&in->device_list,
9374 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9375 is_single_device_type_equal(&in->device_list,
9376 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009377 if (config->sample_rate == 0)
9378 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9379 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9380 config->sample_rate != 8000) {
9381 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9382 ret = -EINVAL;
9383 goto err_open;
9384 }
9385 if (config->format == AUDIO_FORMAT_DEFAULT)
9386 config->format = AUDIO_FORMAT_PCM_16_BIT;
9387 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9388 config->format = AUDIO_FORMAT_PCM_16_BIT;
9389 ret = -EINVAL;
9390 goto err_open;
9391 }
9392
9393 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009394 if (adev->ha_proxy_enable &&
9395 is_single_device_type_equal(&in->device_list,
9396 AUDIO_DEVICE_IN_TELEPHONY_RX))
9397 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009398 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009399 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009400 in->af_period_multiplier = 1;
9401 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9402 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9403 (config->sample_rate == 8000 ||
9404 config->sample_rate == 16000 ||
9405 config->sample_rate == 32000 ||
9406 config->sample_rate == 48000) &&
9407 channel_count == 1) {
9408 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9409 in->config = pcm_config_audio_capture;
9410 frame_size = audio_stream_in_frame_size(&in->stream);
9411 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9412 config->sample_rate,
9413 config->format,
9414 channel_count, false /*is_low_latency*/);
9415 in->config.period_size = buffer_size / frame_size;
9416 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9417 in->config.rate = config->sample_rate;
9418 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009419 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309420 int ret_val;
9421 pthread_mutex_lock(&adev->lock);
9422 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9423 in, config, &channel_mask_updated);
9424 pthread_mutex_unlock(&adev->lock);
9425
9426 if (!ret_val) {
9427 if (channel_mask_updated == true) {
9428 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9429 __func__, config->channel_mask);
9430 ret = -EINVAL;
9431 goto err_open;
9432 }
9433 ALOGD("%s: created multi-channel session succesfully",__func__);
9434 } else if (audio_extn_compr_cap_enabled() &&
9435 audio_extn_compr_cap_format_supported(config->format) &&
9436 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9437 audio_extn_compr_cap_init(in);
9438 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309439 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309440 if (ret)
9441 goto err_open;
9442 } else {
9443 in->config = pcm_config_audio_capture;
9444 in->config.rate = config->sample_rate;
9445 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309446 in->format = config->format;
9447 frame_size = audio_stream_in_frame_size(&in->stream);
9448 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009449 config->format,
9450 channel_count,
9451 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009452 /* prevent division-by-zero */
9453 if (frame_size == 0) {
9454 ALOGE("%s: Error frame_size==0", __func__);
9455 ret = -EINVAL;
9456 goto err_open;
9457 }
9458
Revathi Uddarajud2634032017-12-07 14:42:34 +05309459 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009460 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009461
Revathi Uddarajud2634032017-12-07 14:42:34 +05309462 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9463 /* optionally use VOIP usecase depending on config(s) */
9464 ret = adev_update_voice_comm_input_stream(in, config);
9465 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009466
Revathi Uddarajud2634032017-12-07 14:42:34 +05309467 if (ret) {
9468 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9469 goto err_open;
9470 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009471 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309472
9473 /* assign concurrent capture usecase if record has to caried out from
9474 * actual hardware input source */
9475 if (audio_extn_is_concurrent_capture_enabled() &&
9476 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309477 /* Acquire lock to avoid two concurrent use cases initialized to
9478 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009479
Samyak Jainc37062f2019-04-25 18:41:06 +05309480 if (in->usecase == USECASE_AUDIO_RECORD) {
9481 pthread_mutex_lock(&adev->lock);
9482 if (!(adev->pcm_record_uc_state)) {
9483 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9484 adev->pcm_record_uc_state = 1;
9485 pthread_mutex_unlock(&adev->lock);
9486 } else {
9487 pthread_mutex_unlock(&adev->lock);
9488 /* Assign compress record use case for second record */
9489 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9490 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9491 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9492 if (audio_extn_cin_applicable_stream(in)) {
9493 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309494 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309495 if (ret)
9496 goto err_open;
9497 }
9498 }
9499 }
kunleiz28c73e72019-03-27 17:24:04 +08009500 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009501 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309502 if (audio_extn_ssr_get_stream() != in)
9503 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009504
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009505 in->sample_rate = in->config.rate;
9506
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309507 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9508 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009509 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009510 in->sample_rate, in->bit_width,
9511 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309512 register_format(in->format, in->supported_formats);
9513 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9514 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309515
Aalique Grahame22e49102018-12-18 14:23:57 -08009516 in->error_log = error_log_create(
9517 ERROR_LOG_ENTRIES,
9518 1000000000 /* aggregate consecutive identical errors within one second */);
9519
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009520 /* This stream could be for sound trigger lab,
9521 get sound trigger pcm if present */
9522 audio_extn_sound_trigger_check_and_get_session(in);
9523
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309524 lock_input_stream(in);
9525 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9526 pthread_mutex_lock(&adev->lock);
9527 in->card_status = adev->card_status;
9528 pthread_mutex_unlock(&adev->lock);
9529 pthread_mutex_unlock(&in->lock);
9530
Aalique Grahame22e49102018-12-18 14:23:57 -08009531 stream_app_type_cfg_init(&in->app_type_cfg);
9532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009533 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009534
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009535 ret = io_streams_map_insert(adev, &in->stream.common,
9536 handle, AUDIO_PATCH_HANDLE_NONE);
9537 if (ret != 0)
9538 goto err_open;
9539
Derek Chenf939fb72018-11-13 13:34:41 -08009540 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9541 calloc(1, sizeof(streams_input_ctxt_t));
9542 if (in_ctxt == NULL) {
9543 ALOGE("%s fail to allocate input ctxt", __func__);
9544 ret = -ENOMEM;
9545 goto err_open;
9546 }
9547 in_ctxt->input = in;
9548
9549 pthread_mutex_lock(&adev->lock);
9550 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9551 pthread_mutex_unlock(&adev->lock);
9552
Eric Laurent994a6932013-07-17 11:51:42 -07009553 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009554 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009555
9556err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309557 if (in->usecase == USECASE_AUDIO_RECORD) {
9558 pthread_mutex_lock(&adev->lock);
9559 adev->pcm_record_uc_state = 0;
9560 pthread_mutex_unlock(&adev->lock);
9561 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009562 free(in);
9563 *stream_in = NULL;
9564 return ret;
9565}
9566
9567static void adev_close_input_stream(struct audio_hw_device *dev,
9568 struct audio_stream_in *stream)
9569{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009570 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009571 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009572 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309573
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309574 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009575
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009576 if (in == NULL) {
9577 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9578 return;
9579 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009580 io_streams_map_remove(adev, in->capture_handle);
9581
kunleiz70e57612018-12-28 17:50:23 +08009582 /* must deregister from sndmonitor first to prevent races
9583 * between the callback and close_stream
9584 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309585 audio_extn_snd_mon_unregister_listener(stream);
9586
kunleiz70e57612018-12-28 17:50:23 +08009587 /* Disable echo reference if there are no active input, hfp call
9588 * and sound trigger while closing input stream
9589 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009590 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009591 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009592 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9593 struct listnode out_devices;
9594 list_init(&out_devices);
9595 platform_set_echo_reference(adev, false, &out_devices);
9596 } else
kunleiz70e57612018-12-28 17:50:23 +08009597 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309598
Weiyin Jiang2995f662019-04-17 14:25:12 +08009599 error_log_destroy(in->error_log);
9600 in->error_log = NULL;
9601
Pallavid7c7a272018-01-16 11:22:55 +05309602
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009603 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309604 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009605 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309606 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009607 if (ret != 0)
9608 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9609 __func__, ret);
9610 } else
9611 in_standby(&stream->common);
9612
Revathi Uddarajud2634032017-12-07 14:42:34 +05309613 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309614 if (in->usecase == USECASE_AUDIO_RECORD) {
9615 adev->pcm_record_uc_state = 0;
9616 }
9617
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009618 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9619 adev->enable_voicerx = false;
9620 }
9621
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009622 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009623 audio_extn_ssr_deinit();
9624 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009625
Garmond Leunge2433c32017-09-28 21:51:22 -07009626 if (audio_extn_ffv_get_stream() == in) {
9627 audio_extn_ffv_stream_deinit();
9628 }
9629
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309630 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009631 audio_extn_compr_cap_format_supported(in->config.format))
9632 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309633
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309634 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309635 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009636
Mingming Yinfd7607b2016-01-22 12:48:44 -08009637 if (in->is_st_session) {
9638 ALOGV("%s: sound trigger pcm stop lab", __func__);
9639 audio_extn_sound_trigger_stop_lab(in);
9640 }
Derek Chenf939fb72018-11-13 13:34:41 -08009641 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9642 if (in_ctxt != NULL) {
9643 list_remove(&in_ctxt->list);
9644 free(in_ctxt);
9645 } else {
9646 ALOGW("%s, input stream already closed", __func__);
9647 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009648 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309649 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009650 return;
9651}
9652
Aalique Grahame22e49102018-12-18 14:23:57 -08009653/* verifies input and output devices and their capabilities.
9654 *
9655 * This verification is required when enabling extended bit-depth or
9656 * sampling rates, as not all qcom products support it.
9657 *
9658 * Suitable for calling only on initialization such as adev_open().
9659 * It fills the audio_device use_case_table[] array.
9660 *
9661 * Has a side-effect that it needs to configure audio routing / devices
9662 * in order to power up the devices and read the device parameters.
9663 * It does not acquire any hw device lock. Should restore the devices
9664 * back to "normal state" upon completion.
9665 */
9666static int adev_verify_devices(struct audio_device *adev)
9667{
9668 /* enumeration is a bit difficult because one really wants to pull
9669 * the use_case, device id, etc from the hidden pcm_device_table[].
9670 * In this case there are the following use cases and device ids.
9671 *
9672 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9673 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9674 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9675 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9676 * [USECASE_AUDIO_RECORD] = {0, 0},
9677 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9678 * [USECASE_VOICE_CALL] = {2, 2},
9679 *
9680 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9681 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9682 */
9683
9684 /* should be the usecases enabled in adev_open_input_stream() */
9685 static const int test_in_usecases[] = {
9686 USECASE_AUDIO_RECORD,
9687 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9688 };
9689 /* should be the usecases enabled in adev_open_output_stream()*/
9690 static const int test_out_usecases[] = {
9691 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9692 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9693 };
9694 static const usecase_type_t usecase_type_by_dir[] = {
9695 PCM_PLAYBACK,
9696 PCM_CAPTURE,
9697 };
9698 static const unsigned flags_by_dir[] = {
9699 PCM_OUT,
9700 PCM_IN,
9701 };
9702
9703 size_t i;
9704 unsigned dir;
9705 const unsigned card_id = adev->snd_card;
9706
9707 for (dir = 0; dir < 2; ++dir) {
9708 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9709 const unsigned flags_dir = flags_by_dir[dir];
9710 const size_t testsize =
9711 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9712 const int *testcases =
9713 dir ? test_in_usecases : test_out_usecases;
9714 const audio_devices_t audio_device =
9715 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9716
9717 for (i = 0; i < testsize; ++i) {
9718 const audio_usecase_t audio_usecase = testcases[i];
9719 int device_id;
9720 struct pcm_params **pparams;
9721 struct stream_out out;
9722 struct stream_in in;
9723 struct audio_usecase uc_info;
9724 int retval;
9725
9726 pparams = &adev->use_case_table[audio_usecase];
9727 pcm_params_free(*pparams); /* can accept null input */
9728 *pparams = NULL;
9729
9730 /* find the device ID for the use case (signed, for error) */
9731 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9732 if (device_id < 0)
9733 continue;
9734
9735 /* prepare structures for device probing */
9736 memset(&uc_info, 0, sizeof(uc_info));
9737 uc_info.id = audio_usecase;
9738 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009739 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009740 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009741 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009742 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009743 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009744 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9745 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009746 }
9747 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009748 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009749 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009750 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009751 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009752 uc_info.in_snd_device = SND_DEVICE_NONE;
9753 uc_info.out_snd_device = SND_DEVICE_NONE;
9754 list_add_tail(&adev->usecase_list, &uc_info.list);
9755
9756 /* select device - similar to start_(in/out)put_stream() */
9757 retval = select_devices(adev, audio_usecase);
9758 if (retval >= 0) {
9759 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9760#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009761 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009762 if (*pparams) {
9763 ALOGV("%s: (%s) card %d device %d", __func__,
9764 dir ? "input" : "output", card_id, device_id);
9765 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9766 } else {
9767 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9768 }
9769#endif
9770 }
9771
9772 /* deselect device - similar to stop_(in/out)put_stream() */
9773 /* 1. Get and set stream specific mixer controls */
9774 retval = disable_audio_route(adev, &uc_info);
9775 /* 2. Disable the rx device */
9776 retval = disable_snd_device(adev,
9777 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9778 list_remove(&uc_info.list);
9779 }
9780 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009781 return 0;
9782}
9783
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009784int update_patch(unsigned int num_sources,
9785 const struct audio_port_config *sources,
9786 unsigned int num_sinks,
9787 const struct audio_port_config *sinks,
9788 audio_patch_handle_t handle,
9789 struct audio_patch_info *p_info,
9790 patch_type_t patch_type, bool new_patch)
9791{
9792 ALOGD("%s: enter", __func__);
9793
9794 if (p_info == NULL) {
9795 ALOGE("%s: Invalid patch pointer", __func__);
9796 return -EINVAL;
9797 }
9798
9799 if (new_patch) {
9800 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9801 if (p_info->patch == NULL) {
9802 ALOGE("%s: Could not allocate patch", __func__);
9803 return -ENOMEM;
9804 }
9805 }
9806
9807 p_info->patch->id = handle;
9808 p_info->patch->num_sources = num_sources;
9809 p_info->patch->num_sinks = num_sinks;
9810
9811 for (int i = 0; i < num_sources; i++)
9812 p_info->patch->sources[i] = sources[i];
9813 for (int i = 0; i < num_sinks; i++)
9814 p_info->patch->sinks[i] = sinks[i];
9815
9816 p_info->patch_type = patch_type;
9817 return 0;
9818}
9819
9820audio_patch_handle_t generate_patch_handle()
9821{
9822 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9823 if (++patch_handle < 0)
9824 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9825 return patch_handle;
9826}
9827
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309828int adev_create_audio_patch(struct audio_hw_device *dev,
9829 unsigned int num_sources,
9830 const struct audio_port_config *sources,
9831 unsigned int num_sinks,
9832 const struct audio_port_config *sinks,
9833 audio_patch_handle_t *handle)
9834{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009835 int ret = 0;
9836 struct audio_device *adev = (struct audio_device *)dev;
9837 struct audio_patch_info *p_info = NULL;
9838 patch_type_t patch_type = PATCH_NONE;
9839 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9840 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9841 struct audio_stream_info *s_info = NULL;
9842 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009843 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009844 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9845 bool new_patch = false;
9846 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309847
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009848 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9849 num_sources, num_sinks, *handle);
9850
9851 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9852 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9853 ALOGE("%s: Invalid patch arguments", __func__);
9854 ret = -EINVAL;
9855 goto done;
9856 }
9857
9858 if (num_sources > 1) {
9859 ALOGE("%s: Multiple sources are not supported", __func__);
9860 ret = -EINVAL;
9861 goto done;
9862 }
9863
9864 if (sources == NULL || sinks == NULL) {
9865 ALOGE("%s: Invalid sources or sinks port config", __func__);
9866 ret = -EINVAL;
9867 goto done;
9868 }
9869
9870 ALOGV("%s: source role %d, source type %d", __func__,
9871 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009872 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009873
9874 // Populate source/sink information and fetch stream info
9875 switch (sources[0].type) {
9876 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9877 device_type = sources[0].ext.device.type;
9878 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009879 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009880 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9881 patch_type = PATCH_CAPTURE;
9882 io_handle = sinks[0].ext.mix.handle;
9883 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009884 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009885 __func__, device_type, io_handle);
9886 } else {
9887 // Device to device patch is not implemented.
9888 // This space will need changes if audio HAL
9889 // handles device to device patches in the future.
9890 patch_type = PATCH_DEVICE_LOOPBACK;
9891 }
9892 break;
9893 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9894 io_handle = sources[0].ext.mix.handle;
9895 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009896 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009897 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009898 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009899 }
9900 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009901 ALOGD("%s: Playback patch from mix handle %d to device %x",
9902 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009903 break;
9904 case AUDIO_PORT_TYPE_SESSION:
9905 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009906 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9907 ret = -EINVAL;
9908 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009909 }
9910
9911 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009912
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009913 // Generate patch info and update patch
9914 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009915 *handle = generate_patch_handle();
9916 p_info = (struct audio_patch_info *)
9917 calloc(1, sizeof(struct audio_patch_info));
9918 if (p_info == NULL) {
9919 ALOGE("%s: Failed to allocate memory", __func__);
9920 pthread_mutex_unlock(&adev->lock);
9921 ret = -ENOMEM;
9922 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009923 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009924 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009925 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009926 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009927 if (p_info == NULL) {
9928 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9929 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009930 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009931 ret = -EINVAL;
9932 goto done;
9933 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009934 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009935 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009936 *handle, p_info, patch_type, new_patch);
9937
9938 // Fetch stream info of associated mix for playback or capture patches
9939 if (p_info->patch_type == PATCH_PLAYBACK ||
9940 p_info->patch_type == PATCH_CAPTURE) {
9941 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9942 if (s_info == NULL) {
9943 ALOGE("%s: Failed to obtain stream info", __func__);
9944 if (new_patch)
9945 free(p_info);
9946 pthread_mutex_unlock(&adev->lock);
9947 ret = -EINVAL;
9948 goto done;
9949 }
9950 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9951 s_info->patch_handle = *handle;
9952 stream = s_info->stream;
9953 }
9954 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009955
9956 // Update routing for stream
9957 if (stream != NULL) {
9958 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009959 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009960 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009961 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009962 if (ret < 0) {
9963 pthread_mutex_lock(&adev->lock);
9964 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9965 if (new_patch)
9966 free(p_info);
9967 pthread_mutex_unlock(&adev->lock);
9968 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9969 goto done;
9970 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009971 }
9972
9973 // Add new patch to patch map
9974 if (!ret && new_patch) {
9975 pthread_mutex_lock(&adev->lock);
9976 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009977 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009978 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009979 }
9980
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009981done:
9982 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009983 num_sources,
9984 sources,
9985 num_sinks,
9986 sinks,
9987 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009988 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009989 num_sources,
9990 sources,
9991 num_sinks,
9992 sinks,
9993 handle);
9994 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309995}
9996
9997int adev_release_audio_patch(struct audio_hw_device *dev,
9998 audio_patch_handle_t handle)
9999{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010000 struct audio_device *adev = (struct audio_device *) dev;
10001 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010002 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010003 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010004
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010005 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10006 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10007 ret = -EINVAL;
10008 goto done;
10009 }
10010
10011 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010012 pthread_mutex_lock(&adev->lock);
10013 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010014 if (p_info == NULL) {
10015 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010016 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010017 ret = -EINVAL;
10018 goto done;
10019 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010020 struct audio_patch *patch = p_info->patch;
10021 if (patch == NULL) {
10022 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010023 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010024 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010025 goto done;
10026 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010027 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10028 switch (patch->sources[0].type) {
10029 case AUDIO_PORT_TYPE_MIX:
10030 io_handle = patch->sources[0].ext.mix.handle;
10031 break;
10032 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010033 if (p_info->patch_type == PATCH_CAPTURE)
10034 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010035 break;
10036 case AUDIO_PORT_TYPE_SESSION:
10037 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010038 pthread_mutex_unlock(&adev->lock);
10039 ret = -EINVAL;
10040 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010041 }
10042
10043 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010044 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010045 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010046 if (patch_type == PATCH_PLAYBACK ||
10047 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010048 struct audio_stream_info *s_info =
10049 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10050 if (s_info == NULL) {
10051 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10052 pthread_mutex_unlock(&adev->lock);
10053 goto done;
10054 }
10055 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10056 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010057 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010058 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010059
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010060 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010061 struct listnode devices;
10062 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010063 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010064 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010065 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010066 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010067 }
10068
10069 if (ret < 0)
10070 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10071
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010072done:
10073 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10074 audio_extn_auto_hal_release_audio_patch(dev, handle);
10075
10076 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010077 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010078}
10079
10080int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10081{
Derek Chenf13dd492018-11-13 14:53:51 -080010082 int ret = 0;
10083
10084 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10085 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10086 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010087}
10088
10089int adev_set_audio_port_config(struct audio_hw_device *dev,
10090 const struct audio_port_config *config)
10091{
Derek Chenf13dd492018-11-13 14:53:51 -080010092 int ret = 0;
10093
10094 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10095 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10096 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010097}
10098
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010099static int adev_dump(const audio_hw_device_t *device __unused,
10100 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010101{
10102 return 0;
10103}
10104
10105static int adev_close(hw_device_t *device)
10106{
Aalique Grahame22e49102018-12-18 14:23:57 -080010107 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010108 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010109
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010110 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010111 return 0;
10112
10113 pthread_mutex_lock(&adev_init_lock);
10114
10115 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010116 if (audio_extn_spkr_prot_is_enabled())
10117 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010118 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010119 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010120 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010121 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010122 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010123 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010124 audio_extn_utils_release_streams_cfg_lists(
10125 &adev->streams_output_cfg_list,
10126 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010127 if (audio_extn_qap_is_enabled())
10128 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010129 if (audio_extn_qaf_is_enabled())
10130 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010131 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010132 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010133 free(adev->snd_dev_ref_cnt);
10134 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010135 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10136 pcm_params_free(adev->use_case_table[i]);
10137 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010138 if (adev->adm_deinit)
10139 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010140 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010141 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010142 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010143 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010144 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010145 if (adev->device_cfg_params) {
10146 free(adev->device_cfg_params);
10147 adev->device_cfg_params = NULL;
10148 }
Derek Chend2530072014-11-24 12:39:14 -080010149 if(adev->ext_hw_plugin)
10150 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010151 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010152 free_map(adev->patch_map);
10153 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010154 free(device);
10155 adev = NULL;
10156 }
10157 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010158 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010159 return 0;
10160}
10161
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010162/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10163 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10164 * just that it _might_ work.
10165 */
10166static int period_size_is_plausible_for_low_latency(int period_size)
10167{
10168 switch (period_size) {
10169 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010170 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010171 case 240:
10172 case 320:
10173 case 480:
10174 return 1;
10175 default:
10176 return 0;
10177 }
10178}
10179
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010180static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10181{
10182 bool is_snd_card_status = false;
10183 bool is_ext_device_status = false;
10184 char value[32];
10185 int card = -1;
10186 card_status_t status;
10187
10188 if (cookie != adev || !parms)
10189 return;
10190
10191 if (!parse_snd_card_status(parms, &card, &status)) {
10192 is_snd_card_status = true;
10193 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10194 is_ext_device_status = true;
10195 } else {
10196 // not a valid event
10197 return;
10198 }
10199
10200 pthread_mutex_lock(&adev->lock);
10201 if (card == adev->snd_card || is_ext_device_status) {
10202 if (is_snd_card_status && adev->card_status != status) {
10203 adev->card_status = status;
10204 platform_snd_card_update(adev->platform, status);
10205 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010206 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010207 if (status == CARD_STATUS_OFFLINE)
10208 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010209 } else if (is_ext_device_status) {
10210 platform_set_parameters(adev->platform, parms);
10211 }
10212 }
10213 pthread_mutex_unlock(&adev->lock);
10214 return;
10215}
10216
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010217/* out and adev lock held */
10218static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10219{
10220 struct audio_usecase *uc_info;
10221 float left_p;
10222 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010223 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010224
10225 uc_info = get_usecase_from_list(adev, out->usecase);
10226 if (uc_info == NULL) {
10227 ALOGE("%s: Could not find the usecase (%d) in the list",
10228 __func__, out->usecase);
10229 return -EINVAL;
10230 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010231 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010232
10233 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10234 out->usecase, use_case_table[out->usecase]);
10235
10236 if (restore) {
10237 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010238 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010239 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010240 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10241 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010242 pthread_mutex_lock(&out->compr_mute_lock);
10243 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010244 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010245 out->a2dp_compress_mute = false;
10246 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10247 }
10248 pthread_mutex_unlock(&out->compr_mute_lock);
10249 }
10250 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010251 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10252 // mute compress stream if suspended
10253 pthread_mutex_lock(&out->compr_mute_lock);
10254 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010255 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010256 assign_devices(&devices, &out->device_list);
10257 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010258 left_p = out->volume_l;
10259 right_p = out->volume_r;
10260 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10261 compress_pause(out->compr);
10262 out_set_compr_volume(&out->stream, (float)0, (float)0);
10263 out->a2dp_compress_mute = true;
10264 select_devices(adev, out->usecase);
10265 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10266 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010267 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010268 out->volume_l = left_p;
10269 out->volume_r = right_p;
10270 }
Zhou Songc576a452019-09-09 14:17:40 +080010271 pthread_mutex_unlock(&out->compr_mute_lock);
10272 } else {
10273 // tear down a2dp path for non offloaded streams
10274 if (audio_extn_a2dp_source_is_suspended())
10275 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010276 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010277 }
10278 ALOGV("%s: exit", __func__);
10279 return 0;
10280}
10281
10282int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10283{
10284 int ret = 0;
10285
10286 lock_output_stream(out);
10287 pthread_mutex_lock(&adev->lock);
10288
10289 ret = check_a2dp_restore_l(adev, out, restore);
10290
10291 pthread_mutex_unlock(&adev->lock);
10292 pthread_mutex_unlock(&out->lock);
10293 return ret;
10294}
10295
Haynes Mathew George01156f92018-04-13 15:29:54 -070010296void adev_on_battery_status_changed(bool charging)
10297{
10298 pthread_mutex_lock(&adev->lock);
10299 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10300 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010301 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010302 pthread_mutex_unlock(&adev->lock);
10303}
10304
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010305static int adev_open(const hw_module_t *module, const char *name,
10306 hw_device_t **device)
10307{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010308 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010309 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010310 char mixer_ctl_name[128] = {0};
10311 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010312
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010313 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010314 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10315
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010316 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010317 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010318 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010319 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010320 ALOGD("%s: returning existing instance of adev", __func__);
10321 ALOGD("%s: exit", __func__);
10322 pthread_mutex_unlock(&adev_init_lock);
10323 return 0;
10324 }
10325
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010326 adev = calloc(1, sizeof(struct audio_device));
10327
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010328 if (!adev) {
10329 pthread_mutex_unlock(&adev_init_lock);
10330 return -ENOMEM;
10331 }
10332
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010333 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10334
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010335 // register audio ext hidl at the earliest
10336 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010337#ifdef DYNAMIC_LOG_ENABLED
10338 register_for_dynamic_logging("hal");
10339#endif
10340
Derek Chenf939fb72018-11-13 13:34:41 -080010341 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010342 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010343 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10344 maj_version = atoi(value);
10345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010346 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010347 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010348 adev->device.common.module = (struct hw_module_t *)module;
10349 adev->device.common.close = adev_close;
10350
10351 adev->device.init_check = adev_init_check;
10352 adev->device.set_voice_volume = adev_set_voice_volume;
10353 adev->device.set_master_volume = adev_set_master_volume;
10354 adev->device.get_master_volume = adev_get_master_volume;
10355 adev->device.set_master_mute = adev_set_master_mute;
10356 adev->device.get_master_mute = adev_get_master_mute;
10357 adev->device.set_mode = adev_set_mode;
10358 adev->device.set_mic_mute = adev_set_mic_mute;
10359 adev->device.get_mic_mute = adev_get_mic_mute;
10360 adev->device.set_parameters = adev_set_parameters;
10361 adev->device.get_parameters = adev_get_parameters;
10362 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10363 adev->device.open_output_stream = adev_open_output_stream;
10364 adev->device.close_output_stream = adev_close_output_stream;
10365 adev->device.open_input_stream = adev_open_input_stream;
10366 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010367 adev->device.create_audio_patch = adev_create_audio_patch;
10368 adev->device.release_audio_patch = adev_release_audio_patch;
10369 adev->device.get_audio_port = adev_get_audio_port;
10370 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010371 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010372 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010373
10374 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010375 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010376 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010377 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010378 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010379 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010380 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010381 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010382 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010383 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010384 /* Init audio and voice feature */
10385 audio_extn_feature_init();
10386 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010387 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010388 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010389 list_init(&adev->active_inputs_list);
10390 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010391 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010392 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10393 audio_extn_utils_hash_eq);
10394 if (!adev->io_streams_map) {
10395 ALOGE("%s: Could not create io streams map", __func__);
10396 ret = -ENOMEM;
10397 goto adev_open_err;
10398 }
10399 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10400 audio_extn_utils_hash_eq);
10401 if (!adev->patch_map) {
10402 ALOGE("%s: Could not create audio patch map", __func__);
10403 ret = -ENOMEM;
10404 goto adev_open_err;
10405 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010406 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010407 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010408 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010409 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010410 adev->perf_lock_opts[0] = 0x101;
10411 adev->perf_lock_opts[1] = 0x20E;
10412 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010413 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010414 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010415 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010416 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010417
Zhou Song68ebc352019-12-05 17:11:15 +080010418 audio_extn_perf_lock_init();
10419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010420 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010421 adev->platform = platform_init(adev);
10422 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010423 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010424 ret = -EINVAL;
10425 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010426 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010427
Aalique Grahame22e49102018-12-18 14:23:57 -080010428 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010429 if (audio_extn_qap_is_enabled()) {
10430 ret = audio_extn_qap_init(adev);
10431 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010432 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010433 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010434 }
10435 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10436 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10437 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010438
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010439 if (audio_extn_qaf_is_enabled()) {
10440 ret = audio_extn_qaf_init(adev);
10441 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010442 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010443 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010444 }
10445
10446 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10447 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10448 }
10449
Derek Chenae7b0342019-02-08 15:17:04 -080010450 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010451 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10452
Eric Laurentc4aef752013-09-12 17:45:53 -070010453 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10454 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10455 if (adev->visualizer_lib == NULL) {
10456 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10457 } else {
10458 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10459 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010460 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010461 "visualizer_hal_start_output");
10462 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010463 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010464 "visualizer_hal_stop_output");
10465 }
10466 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010467 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010468 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010469 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010470 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010471 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010472 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010473
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010474 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10475 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10476 if (adev->offload_effects_lib == NULL) {
10477 ALOGE("%s: DLOPEN failed for %s", __func__,
10478 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10479 } else {
10480 ALOGV("%s: DLOPEN successful for %s", __func__,
10481 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10482 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010483 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010484 "offload_effects_bundle_hal_start_output");
10485 adev->offload_effects_stop_output =
10486 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10487 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010488 adev->offload_effects_set_hpx_state =
10489 (int (*)(bool))dlsym(adev->offload_effects_lib,
10490 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010491 adev->offload_effects_get_parameters =
10492 (void (*)(struct str_parms *, struct str_parms *))
10493 dlsym(adev->offload_effects_lib,
10494 "offload_effects_bundle_get_parameters");
10495 adev->offload_effects_set_parameters =
10496 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10497 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010498 }
10499 }
10500
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010501 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10502 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10503 if (adev->adm_lib == NULL) {
10504 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10505 } else {
10506 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10507 adev->adm_init = (adm_init_t)
10508 dlsym(adev->adm_lib, "adm_init");
10509 adev->adm_deinit = (adm_deinit_t)
10510 dlsym(adev->adm_lib, "adm_deinit");
10511 adev->adm_register_input_stream = (adm_register_input_stream_t)
10512 dlsym(adev->adm_lib, "adm_register_input_stream");
10513 adev->adm_register_output_stream = (adm_register_output_stream_t)
10514 dlsym(adev->adm_lib, "adm_register_output_stream");
10515 adev->adm_deregister_stream = (adm_deregister_stream_t)
10516 dlsym(adev->adm_lib, "adm_deregister_stream");
10517 adev->adm_request_focus = (adm_request_focus_t)
10518 dlsym(adev->adm_lib, "adm_request_focus");
10519 adev->adm_abandon_focus = (adm_abandon_focus_t)
10520 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010521 adev->adm_set_config = (adm_set_config_t)
10522 dlsym(adev->adm_lib, "adm_set_config");
10523 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10524 dlsym(adev->adm_lib, "adm_request_focus_v2");
10525 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10526 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10527 adev->adm_on_routing_change = (adm_on_routing_change_t)
10528 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010529 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10530 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010531 }
10532 }
10533
Aalique Grahame22e49102018-12-18 14:23:57 -080010534 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010535 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010536 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010537 //initialize this to false for now,
10538 //this will be set to true through set param
10539 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010540
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010541 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010542 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010543
10544 if (k_enable_extended_precision)
10545 adev_verify_devices(adev);
10546
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010547 adev->dsp_bit_width_enforce_mode =
10548 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010549
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010550 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10551 &adev->streams_output_cfg_list,
10552 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010553
Kiran Kandi910e1862013-10-29 13:29:42 -070010554 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010555
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010556 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010557 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010558 trial = atoi(value);
10559 if (period_size_is_plausible_for_low_latency(trial)) {
10560 pcm_config_low_latency.period_size = trial;
10561 pcm_config_low_latency.start_threshold = trial / 4;
10562 pcm_config_low_latency.avail_min = trial / 4;
10563 configured_low_latency_capture_period_size = trial;
10564 }
10565 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010566 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10567 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010568 trial = atoi(value);
10569 if (period_size_is_plausible_for_low_latency(trial)) {
10570 configured_low_latency_capture_period_size = trial;
10571 }
10572 }
10573
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010574 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10575
Eric Laurent4b084132018-10-19 17:33:43 -070010576 adev->camera_orientation = CAMERA_DEFAULT;
10577
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010578 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010579 af_period_multiplier = atoi(value);
10580 if (af_period_multiplier < 0)
10581 af_period_multiplier = 2;
10582 else if (af_period_multiplier > 4)
10583 af_period_multiplier = 4;
10584
10585 ALOGV("new period_multiplier = %d", af_period_multiplier);
10586 }
10587
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010588 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010589
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010590 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010591 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010592 pthread_mutex_unlock(&adev_init_lock);
10593
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010594 if (adev->adm_init)
10595 adev->adm_data = adev->adm_init();
10596
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010597 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010598 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010599
10600 audio_extn_snd_mon_init();
10601 pthread_mutex_lock(&adev->lock);
10602 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10603 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010604 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10605 /*
10606 * if the battery state callback happens before charging can be queried,
10607 * it will be guarded with the adev->lock held in the cb function and so
10608 * the callback value will reflect the latest state
10609 */
10610 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010611 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010612 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010613 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010614 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010615 /* Allocate memory for Device config params */
10616 adev->device_cfg_params = (struct audio_device_config_param*)
10617 calloc(platform_get_max_codec_backend(),
10618 sizeof(struct audio_device_config_param));
10619 if (adev->device_cfg_params == NULL)
10620 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010621
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010622 /*
10623 * Check if new PSPD matrix mixer control is supported. If not
10624 * supported, then set flag so that old mixer ctrl is sent while
10625 * sending pspd coefficients on older kernel version. Query mixer
10626 * control for default pcm id and channel value one.
10627 */
10628 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10629 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10630
10631 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10632 if (!ctl) {
10633 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10634 __func__, mixer_ctl_name);
10635 adev->use_old_pspd_mix_ctrl = true;
10636 }
10637
Eric Laurent994a6932013-07-17 11:51:42 -070010638 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010639 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010640
10641adev_open_err:
10642 free_map(adev->patch_map);
10643 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010644 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010645 pthread_mutex_destroy(&adev->lock);
10646 free(adev);
10647 adev = NULL;
10648 *device = NULL;
10649 pthread_mutex_unlock(&adev_init_lock);
10650 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010651}
10652
10653static struct hw_module_methods_t hal_module_methods = {
10654 .open = adev_open,
10655};
10656
10657struct audio_module HAL_MODULE_INFO_SYM = {
10658 .common = {
10659 .tag = HARDWARE_MODULE_TAG,
10660 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10661 .hal_api_version = HARDWARE_HAL_API_VERSION,
10662 .id = AUDIO_HARDWARE_MODULE_ID,
10663 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010664 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010665 .methods = &hal_module_methods,
10666 },
10667};