blob: 2c90c624c6a2d93a22bab3f9031951e1bf09c0f7 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080081#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080082
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053083#ifdef DYNAMIC_LOG_ENABLED
84#include <log_xml_parser.h>
85#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
86#include <log_utils.h>
87#endif
88
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053090/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
91#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070093#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070094#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053095#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053096#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070097#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070098#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070099
Aalique Grahame22e49102018-12-18 14:23:57 -0800100#define RECORD_GAIN_MIN 0.0f
101#define RECORD_GAIN_MAX 1.0f
102#define RECORD_VOLUME_CTL_MAX 0x2000
103
104/* treat as unsigned Q1.13 */
105#define APP_TYPE_GAIN_DEFAULT 0x2000
106
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700107#define PROXY_OPEN_RETRY_COUNT 100
108#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800109
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800110#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
111 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
112 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
113#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
114 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800115
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700116#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700117#define DEFAULT_VOIP_BUF_DURATION_MS 20
118#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
119#define DEFAULT_VOIP_SAMP_RATE 48000
120
121#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
122
123struct pcm_config default_pcm_config_voip_copp = {
124 .channels = 1,
125 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
126 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
127 .period_count = 2,
128 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800129 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
130 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700131};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700132
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700133#define MIN_CHANNEL_COUNT 1
134#define DEFAULT_CHANNEL_COUNT 2
135#define MAX_HIFI_CHANNEL_COUNT 8
136
Aalique Grahame22e49102018-12-18 14:23:57 -0800137#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
138#define MAX_CHANNEL_COUNT 1
139#else
140#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
141#define XSTR(x) STR(x)
142#define STR(x) #x
143#endif
144
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700145static unsigned int configured_low_latency_capture_period_size =
146 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
147
Haynes Mathew George16081042017-05-31 17:16:49 -0700148#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
149#define MMAP_PERIOD_COUNT_MIN 32
150#define MMAP_PERIOD_COUNT_MAX 512
151#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
152
Aalique Grahame22e49102018-12-18 14:23:57 -0800153/* This constant enables extended precision handling.
154 * TODO The flag is off until more testing is done.
155 */
156static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700157extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800158
Eric Laurentb23d5282013-05-14 15:27:20 -0700159struct pcm_config pcm_config_deep_buffer = {
160 .channels = 2,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
163 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
166 .stop_threshold = INT_MAX,
167 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
168};
169
170struct pcm_config pcm_config_low_latency = {
171 .channels = 2,
172 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
173 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
174 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
175 .format = PCM_FORMAT_S16_LE,
176 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
177 .stop_threshold = INT_MAX,
178 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
179};
180
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800181struct pcm_config pcm_config_haptics_audio = {
182 .channels = 1,
183 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
184 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
185 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
187 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
188 .stop_threshold = INT_MAX,
189 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
190};
191
192struct pcm_config pcm_config_haptics = {
193 .channels = 1,
194 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
195 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
196 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
197 .format = PCM_FORMAT_S16_LE,
198 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
199 .stop_threshold = INT_MAX,
200 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
201};
202
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700203static int af_period_multiplier = 4;
204struct pcm_config pcm_config_rt = {
205 .channels = 2,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = ULL_PERIOD_SIZE, //1 ms
208 .period_count = 512, //=> buffer size is 512ms
209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = ULL_PERIOD_SIZE, //1 ms
215};
216
Eric Laurentb23d5282013-05-14 15:27:20 -0700217struct pcm_config pcm_config_hdmi_multi = {
218 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
219 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
220 .period_size = HDMI_MULTI_PERIOD_SIZE,
221 .period_count = HDMI_MULTI_PERIOD_COUNT,
222 .format = PCM_FORMAT_S16_LE,
223 .start_threshold = 0,
224 .stop_threshold = INT_MAX,
225 .avail_min = 0,
226};
227
Haynes Mathew George16081042017-05-31 17:16:49 -0700228struct pcm_config pcm_config_mmap_playback = {
229 .channels = 2,
230 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
231 .period_size = MMAP_PERIOD_SIZE,
232 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
233 .format = PCM_FORMAT_S16_LE,
234 .start_threshold = MMAP_PERIOD_SIZE*8,
235 .stop_threshold = INT32_MAX,
236 .silence_threshold = 0,
237 .silence_size = 0,
238 .avail_min = MMAP_PERIOD_SIZE, //1 ms
239};
240
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700241struct pcm_config pcm_config_hifi = {
242 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
243 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
244 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
245 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
246 .format = PCM_FORMAT_S24_3LE,
247 .start_threshold = 0,
248 .stop_threshold = INT_MAX,
249 .avail_min = 0,
250};
251
Eric Laurentb23d5282013-05-14 15:27:20 -0700252struct pcm_config pcm_config_audio_capture = {
253 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700254 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
255 .format = PCM_FORMAT_S16_LE,
256};
257
Haynes Mathew George16081042017-05-31 17:16:49 -0700258struct pcm_config pcm_config_mmap_capture = {
259 .channels = 2,
260 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
261 .period_size = MMAP_PERIOD_SIZE,
262 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
263 .format = PCM_FORMAT_S16_LE,
264 .start_threshold = 0,
265 .stop_threshold = INT_MAX,
266 .silence_threshold = 0,
267 .silence_size = 0,
268 .avail_min = MMAP_PERIOD_SIZE, //1 ms
269};
270
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700271#define AFE_PROXY_CHANNEL_COUNT 2
272#define AFE_PROXY_SAMPLING_RATE 48000
273
274#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
275#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
276
277struct pcm_config pcm_config_afe_proxy_playback = {
278 .channels = AFE_PROXY_CHANNEL_COUNT,
279 .rate = AFE_PROXY_SAMPLING_RATE,
280 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
281 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
282 .format = PCM_FORMAT_S16_LE,
283 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
284 .stop_threshold = INT_MAX,
285 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286};
287
288#define AFE_PROXY_RECORD_PERIOD_SIZE 768
289#define AFE_PROXY_RECORD_PERIOD_COUNT 4
290
Aalique Grahame22e49102018-12-18 14:23:57 -0800291struct pcm_config pcm_config_audio_capture_rt = {
292 .channels = 2,
293 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
294 .period_size = ULL_PERIOD_SIZE,
295 .period_count = 512,
296 .format = PCM_FORMAT_S16_LE,
297 .start_threshold = 0,
298 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
299 .silence_threshold = 0,
300 .silence_size = 0,
301 .avail_min = ULL_PERIOD_SIZE, //1 ms
302};
303
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700304struct pcm_config pcm_config_afe_proxy_record = {
305 .channels = AFE_PROXY_CHANNEL_COUNT,
306 .rate = AFE_PROXY_SAMPLING_RATE,
307 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
308 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
309 .format = PCM_FORMAT_S16_LE,
310 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
311 .stop_threshold = INT_MAX,
312 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
313};
314
Ashish Jainf1eaa582016-05-23 20:54:24 +0530315#define AUDIO_MAX_PCM_FORMATS 7
316
317const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
318 [AUDIO_FORMAT_DEFAULT] = 0,
319 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
320 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
321 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
322 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
323 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
324 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
325};
326
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800327const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700328 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
329 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800330 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800331 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700332 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
333 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700334 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700335 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700336 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
341 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700344 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
345 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700346 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800347 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700348
Eric Laurentb23d5282013-05-14 15:27:20 -0700349 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700350 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530351 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
352 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
353 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530354 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
355 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700356 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700357 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700358 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700359 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700360
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800361 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800362 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400363 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
364 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700365
Derek Chenf7092792017-05-23 12:23:53 -0400366 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700367 [USECASE_VOICE2_CALL] = "voice2-call",
368 [USECASE_VOLTE_CALL] = "volte-call",
369 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800370 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800371 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
372 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800373 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700374 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
375 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
376 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800377 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
378 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
379 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
380
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700381 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
382 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700383 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
384 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700385
386 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
387 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800388 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530389 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700390
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530391 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530392 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
393 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700394
395 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
396 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530397 /* For Interactive Audio Streams */
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
401 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
402 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
403 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700406
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800407 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
408
Derek Chenf6318be2017-06-12 17:16:24 -0400409 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
410
411 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
412 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
413 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
414 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800415 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700416 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530417 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700418};
419
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700420static const audio_usecase_t offload_usecases[] = {
421 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700422 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
426 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
427 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
428 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700430};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800431
Varun Balaraje49253e2017-07-06 19:48:56 +0530432static const audio_usecase_t interactive_usecases[] = {
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
437 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
438 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
441};
442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443#define STRING_TO_ENUM(string) { #string, string }
444
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800445struct string_to_enum {
446 const char *name;
447 uint32_t value;
448};
449
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700450static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700455 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800456 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700459 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
460 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
461 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
466 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
467 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800470};
471
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700472static const struct string_to_enum formats_name_to_enum_table[] = {
473 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
474 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
475 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700476 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
477 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
478 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700479 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800480 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
481 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700482 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800483};
484
485//list of all supported sample rates by HDMI specification.
486static const int out_hdmi_sample_rates[] = {
487 32000, 44100, 48000, 88200, 96000, 176400, 192000,
488};
489
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700490static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800491 STRING_TO_ENUM(32000),
492 STRING_TO_ENUM(44100),
493 STRING_TO_ENUM(48000),
494 STRING_TO_ENUM(88200),
495 STRING_TO_ENUM(96000),
496 STRING_TO_ENUM(176400),
497 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800498 STRING_TO_ENUM(352800),
499 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700500};
501
Carter Hsu2e429db2019-05-14 18:50:52 +0800502struct in_effect_list {
503 struct listnode list;
504 effect_handle_t handle;
505};
506
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700507static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700508static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700509static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700510//cache last MBDRC cal step level
511static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700512
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530513static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
514static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700515static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800516static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530517static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530518
Derek Chen6f293672019-04-01 01:40:24 -0700519static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
520static void in_snd_mon_cb(void * stream, struct str_parms * parms);
521static void out_snd_mon_cb(void * stream, struct str_parms * parms);
522
Zhou Song331c8e52019-08-26 14:16:12 +0800523static int configure_btsco_sample_rate(snd_device_t snd_device);
524
Vatsal Buchac09ae062018-11-14 13:25:08 +0530525#ifdef AUDIO_FEATURE_ENABLED_GCOV
526extern void __gcov_flush();
527static void enable_gcov()
528{
529 __gcov_flush();
530}
531#else
532static void enable_gcov()
533{
534}
535#endif
536
justinweng20fb6d82019-02-21 18:49:00 -0700537static int in_set_microphone_direction(const struct audio_stream_in *stream,
538 audio_microphone_direction_t dir);
539static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
540
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700541static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
542 int flags __unused)
543{
544 int dir = 0;
545 switch (uc_id) {
546 case USECASE_AUDIO_RECORD_LOW_LATENCY:
547 dir = 1;
548 case USECASE_AUDIO_PLAYBACK_ULL:
549 break;
550 default:
551 return false;
552 }
553
554 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
555 PCM_PLAYBACK : PCM_CAPTURE);
556 if (adev->adm_is_noirq_avail)
557 return adev->adm_is_noirq_avail(adev->adm_data,
558 adev->snd_card, dev_id, dir);
559 return false;
560}
561
562static void register_out_stream(struct stream_out *out)
563{
564 struct audio_device *adev = out->dev;
565 if (is_offload_usecase(out->usecase) ||
566 !adev->adm_register_output_stream)
567 return;
568
569 // register stream first for backward compatibility
570 adev->adm_register_output_stream(adev->adm_data,
571 out->handle,
572 out->flags);
573
574 if (!adev->adm_set_config)
575 return;
576
577 if (out->realtime)
578 adev->adm_set_config(adev->adm_data,
579 out->handle,
580 out->pcm, &out->config);
581}
582
583static void register_in_stream(struct stream_in *in)
584{
585 struct audio_device *adev = in->dev;
586 if (!adev->adm_register_input_stream)
587 return;
588
589 adev->adm_register_input_stream(adev->adm_data,
590 in->capture_handle,
591 in->flags);
592
593 if (!adev->adm_set_config)
594 return;
595
596 if (in->realtime)
597 adev->adm_set_config(adev->adm_data,
598 in->capture_handle,
599 in->pcm,
600 &in->config);
601}
602
603static void request_out_focus(struct stream_out *out, long ns)
604{
605 struct audio_device *adev = out->dev;
606
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700607 if (adev->adm_request_focus_v2)
608 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
609 else if (adev->adm_request_focus)
610 adev->adm_request_focus(adev->adm_data, out->handle);
611}
612
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700613static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700614{
615 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700616 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700617
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700618 if (adev->adm_request_focus_v2_1)
619 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
620 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
622 else if (adev->adm_request_focus)
623 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700624
625 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700626}
627
628static void release_out_focus(struct stream_out *out)
629{
630 struct audio_device *adev = out->dev;
631
632 if (adev->adm_abandon_focus)
633 adev->adm_abandon_focus(adev->adm_data, out->handle);
634}
635
636static void release_in_focus(struct stream_in *in)
637{
638 struct audio_device *adev = in->dev;
639 if (adev->adm_abandon_focus)
640 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
641}
642
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530643static int parse_snd_card_status(struct str_parms *parms, int *card,
644 card_status_t *status)
645{
646 char value[32]={0};
647 char state[32]={0};
648
649 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
650 if (ret < 0)
651 return -1;
652
653 // sscanf should be okay as value is of max length 32.
654 // same as sizeof state.
655 if (sscanf(value, "%d,%s", card, state) < 2)
656 return -1;
657
658 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
659 CARD_STATUS_OFFLINE;
660 return 0;
661}
662
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700663static inline void adjust_frames_for_device_delay(struct stream_out *out,
664 uint32_t *dsp_frames) {
665 // Adjustment accounts for A2dp encoder latency with offload usecases
666 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800667 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700668 unsigned long offset =
669 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
670 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
671 }
672}
673
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700674static inline bool free_entry(void *key __unused,
675 void *value, void *context __unused)
676{
677 free(value);
678 return true;
679}
680
681static inline void free_map(Hashmap *map)
682{
683 if (map) {
684 hashmapForEach(map, free_entry, (void *) NULL);
685 hashmapFree(map);
686 }
687}
688
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800689static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700690 audio_patch_handle_t patch_handle)
691{
692 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
693 return;
694
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700695 struct audio_patch_info *p_info =
696 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
697 if (p_info) {
698 ALOGV("%s: Remove patch %d", __func__, patch_handle);
699 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
700 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700701 free(p_info);
702 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700703}
704
705static inline int io_streams_map_insert(struct audio_device *adev,
706 struct audio_stream *stream,
707 audio_io_handle_t handle,
708 audio_patch_handle_t patch_handle)
709{
710 struct audio_stream_info *s_info =
711 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
712
713 if (s_info == NULL) {
714 ALOGE("%s: Could not allocate stream info", __func__);
715 return -ENOMEM;
716 }
717 s_info->stream = stream;
718 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700719
720 pthread_mutex_lock(&adev->lock);
721 struct audio_stream_info *stream_info =
722 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700723 if (stream_info != NULL)
724 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800725 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700726 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
727 return 0;
728}
729
730static inline void io_streams_map_remove(struct audio_device *adev,
731 audio_io_handle_t handle)
732{
733 pthread_mutex_lock(&adev->lock);
734 struct audio_stream_info *s_info =
735 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700736 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800737 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700738 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800739 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700740 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800741done:
742 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 return;
744}
745
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800746static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 audio_patch_handle_t handle)
748{
749 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700750 p_info = (struct audio_patch_info *)
751 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700752 return p_info;
753}
754
vivek mehtaa76401a2015-04-24 14:12:15 -0700755__attribute__ ((visibility ("default")))
756bool audio_hw_send_gain_dep_calibration(int level) {
757 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700758 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700759
760 pthread_mutex_lock(&adev_init_lock);
761
762 if (adev != NULL && adev->platform != NULL) {
763 pthread_mutex_lock(&adev->lock);
764 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700765
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530766 // cache level info for any of the use case which
767 // was not started.
768 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700769
vivek mehtaa76401a2015-04-24 14:12:15 -0700770 pthread_mutex_unlock(&adev->lock);
771 } else {
772 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
773 }
774
775 pthread_mutex_unlock(&adev_init_lock);
776
777 return ret_val;
778}
779
Ashish Jain5106d362016-05-11 19:23:33 +0530780static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
781{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800782 bool gapless_enabled = false;
783 const char *mixer_ctl_name = "Compress Gapless Playback";
784 struct mixer_ctl *ctl;
785
786 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700787 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530788
789 /*Disable gapless if its AV playback*/
790 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800791
792 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
793 if (!ctl) {
794 ALOGE("%s: Could not get ctl for mixer cmd - %s",
795 __func__, mixer_ctl_name);
796 return -EINVAL;
797 }
798
799 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
800 ALOGE("%s: Could not set gapless mode %d",
801 __func__, gapless_enabled);
802 return -EINVAL;
803 }
804 return 0;
805}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700806
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700807__attribute__ ((visibility ("default")))
808int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
809 int table_size) {
810 int ret_val = 0;
811 ALOGV("%s: enter ... ", __func__);
812
813 pthread_mutex_lock(&adev_init_lock);
814 if (adev == NULL) {
815 ALOGW("%s: adev is NULL .... ", __func__);
816 goto done;
817 }
818
819 pthread_mutex_lock(&adev->lock);
820 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
821 pthread_mutex_unlock(&adev->lock);
822done:
823 pthread_mutex_unlock(&adev_init_lock);
824 ALOGV("%s: exit ... ", __func__);
825 return ret_val;
826}
827
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800828bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800829{
830 bool ret = false;
831 ALOGV("%s: enter ...", __func__);
832
833 pthread_mutex_lock(&adev_init_lock);
834
835 if (adev != NULL && adev->platform != NULL) {
836 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800837 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800838 pthread_mutex_unlock(&adev->lock);
839 }
840
841 pthread_mutex_unlock(&adev_init_lock);
842
843 ALOGV("%s: exit with ret %d", __func__, ret);
844 return ret;
845}
Aalique Grahame22e49102018-12-18 14:23:57 -0800846
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700847static bool is_supported_format(audio_format_t format)
848{
Eric Laurent86e17132013-09-12 17:49:30 -0700849 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530850 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530851 format == AUDIO_FORMAT_AAC_LC ||
852 format == AUDIO_FORMAT_AAC_HE_V1 ||
853 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530854 format == AUDIO_FORMAT_AAC_ADTS_LC ||
855 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
856 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530857 format == AUDIO_FORMAT_AAC_LATM_LC ||
858 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
859 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530860 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
861 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530862 format == AUDIO_FORMAT_PCM_FLOAT ||
863 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700864 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530865 format == AUDIO_FORMAT_AC3 ||
866 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700867 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530868 format == AUDIO_FORMAT_DTS ||
869 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800870 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530871 format == AUDIO_FORMAT_ALAC ||
872 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530873 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530874 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800875 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530876 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700877 format == AUDIO_FORMAT_APTX ||
878 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800879 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700880
881 return false;
882}
883
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700884static inline bool is_mmap_usecase(audio_usecase_t uc_id)
885{
886 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800887 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700888 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
889}
890
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700891static inline bool is_valid_volume(float left, float right)
892{
893 return ((left >= 0.0f && right >= 0.0f) ? true : false);
894}
895
Avinash Vaish71a8b972014-07-24 15:36:33 +0530896static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
897 struct audio_usecase *uc_info)
898{
899 struct listnode *node;
900 struct audio_usecase *usecase;
901
902 if (uc_info == NULL)
903 return -EINVAL;
904
905 /* Re-route all voice usecases on the shared backend other than the
906 specified usecase to new snd devices */
907 list_for_each(node, &adev->usecase_list) {
908 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800909 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530910 enable_audio_route(adev, usecase);
911 }
912 return 0;
913}
914
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530915static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530916{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530917 ALOGV("%s", __func__);
918 audio_route_apply_and_update_path(adev->audio_route,
919 "asrc-mode");
920 adev->asrc_mode_enabled = true;
921}
922
923static void disable_asrc_mode(struct audio_device *adev)
924{
925 ALOGV("%s", __func__);
926 audio_route_reset_and_update_path(adev->audio_route,
927 "asrc-mode");
928 adev->asrc_mode_enabled = false;
929}
930
931/*
932 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
933 * 44.1 or Native DSD backends are enabled for any of current use case.
934 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
935 * - Disable current mix path use case(Headphone backend) and re-enable it with
936 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
937 * e.g. Naitve DSD or Headphone 44.1 -> + 48
938 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530939static void check_and_set_asrc_mode(struct audio_device *adev,
940 struct audio_usecase *uc_info,
941 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530942{
943 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530944 int i, num_new_devices = 0;
945 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
946 /*
947 *Split snd device for new combo use case
948 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
949 */
950 if (platform_split_snd_device(adev->platform,
951 snd_device,
952 &num_new_devices,
953 split_new_snd_devices) == 0) {
954 for (i = 0; i < num_new_devices; i++)
955 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
956 } else {
957 int new_backend_idx = platform_get_backend_index(snd_device);
958 if (((new_backend_idx == HEADPHONE_BACKEND) ||
959 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
960 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
961 !adev->asrc_mode_enabled) {
962 struct listnode *node = NULL;
963 struct audio_usecase *uc = NULL;
964 struct stream_out *curr_out = NULL;
965 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
966 int i, num_devices, ret = 0;
967 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530968
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530969 list_for_each(node, &adev->usecase_list) {
970 uc = node_to_item(node, struct audio_usecase, list);
971 curr_out = (struct stream_out*) uc->stream.out;
972 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
973 /*
974 *Split snd device for existing combo use case
975 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
976 */
977 ret = platform_split_snd_device(adev->platform,
978 uc->out_snd_device,
979 &num_devices,
980 split_snd_devices);
981 if (ret < 0 || num_devices == 0) {
982 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
983 split_snd_devices[0] = uc->out_snd_device;
984 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800985 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530986 for (i = 0; i < num_devices; i++) {
987 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
988 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
989 if((new_backend_idx == HEADPHONE_BACKEND) &&
990 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
991 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
992 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
993 __func__);
994 enable_asrc_mode(adev);
995 break;
996 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
997 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
998 (usecase_backend_idx == HEADPHONE_BACKEND)) {
999 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
1000 __func__);
1001 disable_audio_route(adev, uc);
1002 disable_snd_device(adev, uc->out_snd_device);
1003 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1004 if (new_backend_idx == DSD_NATIVE_BACKEND)
1005 audio_route_apply_and_update_path(adev->audio_route,
1006 "hph-true-highquality-mode");
1007 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1008 (curr_out->bit_width >= 24))
1009 audio_route_apply_and_update_path(adev->audio_route,
1010 "hph-highquality-mode");
1011 enable_asrc_mode(adev);
1012 enable_snd_device(adev, uc->out_snd_device);
1013 enable_audio_route(adev, uc);
1014 break;
1015 }
1016 }
1017 // reset split devices count
1018 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001019 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301020 if (adev->asrc_mode_enabled)
1021 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301022 }
1023 }
1024 }
1025}
1026
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001027static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1028 struct audio_effect_config effect_config,
1029 unsigned int param_value)
1030{
1031 char mixer_ctl_name[] = "Audio Effect";
1032 struct mixer_ctl *ctl;
1033 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001034 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001035
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001036 if (in == NULL) {
1037 ALOGE("%s: active input stream is NULL", __func__);
1038 return -EINVAL;
1039 }
1040
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001041 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1042 if (!ctl) {
1043 ALOGE("%s: Could not get mixer ctl - %s",
1044 __func__, mixer_ctl_name);
1045 return -EINVAL;
1046 }
1047
1048 set_values[0] = 1; //0:Rx 1:Tx
1049 set_values[1] = in->app_type_cfg.app_type;
1050 set_values[2] = (long)effect_config.module_id;
1051 set_values[3] = (long)effect_config.instance_id;
1052 set_values[4] = (long)effect_config.param_id;
1053 set_values[5] = param_value;
1054
1055 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1056
1057 return 0;
1058
1059}
1060
1061static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1062 int effect_type, unsigned int *param_value)
1063{
1064 int ret = 0;
1065 struct audio_effect_config other_effect_config;
1066 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001067 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001068
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001069 if (in == NULL) {
1070 ALOGE("%s: active input stream is NULL", __func__);
1071 return -EINVAL;
1072 }
1073
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001074 usecase = get_usecase_from_list(adev, in->usecase);
1075 if (!usecase)
1076 return -EINVAL;
1077
1078 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1079 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1080 if (ret < 0) {
1081 ALOGE("%s Failed to get effect params %d", __func__, ret);
1082 return ret;
1083 }
1084
1085 if (module_id == other_effect_config.module_id) {
1086 //Same module id for AEC/NS. Values need to be combined
1087 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1088 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1089 *param_value |= other_effect_config.param_value;
1090 }
1091 }
1092
1093 return ret;
1094}
1095
1096static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301097{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001098 struct audio_effect_config effect_config;
1099 struct audio_usecase *usecase = NULL;
1100 int ret = 0;
1101 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001102 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001103
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001104 if(!voice_extn_is_dynamic_ecns_enabled())
1105 return ENOSYS;
1106
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001107 if (!in) {
1108 ALOGE("%s: Invalid input stream", __func__);
1109 return -EINVAL;
1110 }
1111
1112 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1113
1114 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001115 if (usecase == NULL) {
1116 ALOGE("%s: Could not find the usecase (%d) in the list",
1117 __func__, in->usecase);
1118 return -EINVAL;
1119 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001120
1121 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1122 if (ret < 0) {
1123 ALOGE("%s Failed to get module id %d", __func__, ret);
1124 return ret;
1125 }
1126 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1127 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1128
1129 if(enable)
1130 param_value = effect_config.param_value;
1131
1132 /*Special handling for AEC & NS effects Param values need to be
1133 updated if module ids are same*/
1134
1135 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1136 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1137 if (ret < 0)
1138 return ret;
1139 }
1140
1141 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1142
1143 return ret;
1144}
1145
1146static void check_and_enable_effect(struct audio_device *adev)
1147{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001148 if(!voice_extn_is_dynamic_ecns_enabled())
1149 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001150
Eric Laurent637e2d42018-11-15 12:24:31 -08001151 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001152
Eric Laurent637e2d42018-11-15 12:24:31 -08001153 if (in != NULL && !in->standby) {
1154 if (in->enable_aec)
1155 enable_disable_effect(adev, EFFECT_AEC, true);
1156
1157 if (in->enable_ns &&
1158 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1159 enable_disable_effect(adev, EFFECT_NS, true);
1160 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001161 }
1162}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001163
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001164int pcm_ioctl(struct pcm *pcm, int request, ...)
1165{
1166 va_list ap;
1167 void * arg;
1168 int pcm_fd = *(int*)pcm;
1169
1170 va_start(ap, request);
1171 arg = va_arg(ap, void *);
1172 va_end(ap);
1173
1174 return ioctl(pcm_fd, request, arg);
1175}
1176
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001177int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001178 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001179{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001180 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001181 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301182 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301183 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001184 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301185 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001186
1187 if (usecase == NULL)
1188 return -EINVAL;
1189
1190 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1191
Carter Hsu2e429db2019-05-14 18:50:52 +08001192 if (usecase->type == PCM_CAPTURE) {
1193 struct stream_in *in = usecase->stream.in;
1194 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001195 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001196
1197 if (in) {
1198 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001199 list_init(&out_devices);
1200 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001201 struct listnode *node;
1202 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1203 USECASE_AUDIO_PLAYBACK_VOIP);
1204 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001205 assign_devices(&out_devices,
1206 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001207 } else if (adev->primary_output &&
1208 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001209 assign_devices(&out_devices,
1210 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001211 } else {
1212 list_for_each(node, &adev->usecase_list) {
1213 uinfo = node_to_item(node, struct audio_usecase, list);
1214 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001215 assign_devices(&out_devices,
1216 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001217 break;
1218 }
1219 }
1220 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001221
1222 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001223 in->ec_opened = true;
1224 }
1225 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001226 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1227 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1228 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001229 snd_device = usecase->in_snd_device;
1230 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001231 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001232 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001233
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001234#ifdef DS1_DOLBY_DAP_ENABLED
1235 audio_extn_dolby_set_dmid(adev);
1236 audio_extn_dolby_set_endpoint(adev);
1237#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001238 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001239 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301240 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001241 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001242 if (audio_extn_is_maxx_audio_enabled())
1243 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301244 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301245 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1246 out = usecase->stream.out;
1247 if (out && out->compr)
1248 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1249 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301250
1251 if (usecase->type == PCM_CAPTURE) {
1252 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001253 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301254 ALOGD("%s: set custom mtmx params v1", __func__);
1255 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1256 }
1257 } else {
1258 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1259 }
Manish Dewangan58229382017-02-02 15:48:41 +05301260
Andy Hung756ecc12018-10-19 17:47:12 -07001261 // we shouldn't truncate mixer_path
1262 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1263 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1264 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001265 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001266 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301267 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1268 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1269 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1270 if (parms) {
1271 audio_extn_fm_set_parameters(adev, parms);
1272 str_parms_destroy(parms);
1273 }
1274 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275 ALOGV("%s: exit", __func__);
1276 return 0;
1277}
1278
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001279int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001280 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001282 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001283 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301284 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001285
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301286 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001287 return -EINVAL;
1288
1289 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301290 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001291 snd_device = usecase->in_snd_device;
1292 else
1293 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001294
1295 /* disable island and power mode on supported device for voice call */
1296 if (usecase->type == VOICE_CALL) {
1297 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1298 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1299 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1300 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1301 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1302 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
1303 ALOGD("%s: disable island cfg and power mode in voice tx path",
1304 __func__);
1305 }
1306 }
1307 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1308 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1309 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1310 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1311 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1312 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1313 ALOGD("%s: disable island cfg and power mode in voice rx path",
1314 __func__);
1315 }
1316 }
1317 }
1318
Andy Hung756ecc12018-10-19 17:47:12 -07001319 // we shouldn't truncate mixer_path
1320 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1321 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1322 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001323 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001324 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001325 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001326 if (usecase->type == PCM_CAPTURE) {
1327 struct stream_in *in = usecase->stream.in;
1328 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001329 struct listnode out_devices;
1330 list_init(&out_devices);
1331 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001332 in->ec_opened = false;
1333 }
1334 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001335 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301336 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301337
1338 if (usecase->type == PCM_CAPTURE) {
1339 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001340 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301341 ALOGD("%s: reset custom mtmx params v1", __func__);
1342 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1343 }
1344 } else {
1345 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1346 }
1347
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001348 if ((usecase->type == PCM_PLAYBACK) &&
1349 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301350 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001352 ALOGV("%s: exit", __func__);
1353 return 0;
1354}
1355
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001356int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001357 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001358{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301359 int i, num_devices = 0;
1360 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001361 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1362
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001363 if (snd_device < SND_DEVICE_MIN ||
1364 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001365 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001366 return -EINVAL;
1367 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001368
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001369 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001370 ALOGE("%s: Invalid sound device returned", __func__);
1371 return -EINVAL;
1372 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001373
1374 adev->snd_dev_ref_cnt[snd_device]++;
1375
1376 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1377 (platform_split_snd_device(adev->platform,
1378 snd_device,
1379 &num_devices,
1380 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001381 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001382 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001383 return 0;
1384 }
1385
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001386 if (audio_extn_spkr_prot_is_enabled())
1387 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001388
Aalique Grahame22e49102018-12-18 14:23:57 -08001389 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1390
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001391 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1392 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001393 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1394 goto err;
1395 }
1396 audio_extn_dev_arbi_acquire(snd_device);
1397 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001398 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001399 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001400 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001401 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001402 } else if (platform_split_snd_device(adev->platform,
1403 snd_device,
1404 &num_devices,
1405 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301406 for (i = 0; i < num_devices; i++) {
1407 enable_snd_device(adev, new_snd_devices[i]);
1408 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001409 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001410 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001411 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301412
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001413 /* enable island and power mode on supported device */
1414 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1415 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1416 platform_set_island_cfg_on_device(adev, snd_device, true);
1417 platform_set_power_mode_on_device(adev, snd_device, true);
1418 ALOGD("%s: enable island cfg and power mode on: %s",
1419 __func__, device_name);
1420 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301421
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001422 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1423 (audio_extn_a2dp_start_playback() < 0)) {
1424 ALOGE(" fail to configure A2dp Source control path ");
1425 goto err;
1426 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001427
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001428 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1429 (audio_extn_a2dp_start_capture() < 0)) {
1430 ALOGE(" fail to configure A2dp Sink control path ");
1431 goto err;
1432 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301433
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001434 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1435 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1436 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1437 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1438 ALOGE(" fail to configure sco control path ");
1439 goto err;
1440 }
Zhou Song12c29502019-03-16 10:37:18 +08001441 }
1442
Zhou Song331c8e52019-08-26 14:16:12 +08001443 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001444 /* due to the possibility of calibration overwrite between listen
1445 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001446 audio_extn_sound_trigger_update_device_status(snd_device,
1447 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301448 audio_extn_listen_update_device_status(snd_device,
1449 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001450 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001451 audio_extn_sound_trigger_update_device_status(snd_device,
1452 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301453 audio_extn_listen_update_device_status(snd_device,
1454 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001455 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001456 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001457 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001458 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301459
1460 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1461 !adev->native_playback_enabled &&
1462 audio_is_true_native_stream_active(adev)) {
1463 ALOGD("%s: %d: napb: enabling native mode in hardware",
1464 __func__, __LINE__);
1465 audio_route_apply_and_update_path(adev->audio_route,
1466 "true-native-mode");
1467 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301468 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301469 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1470 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001471 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001472 ALOGD("%s: init ec ref loopback", __func__);
1473 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1474 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001476 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001477err:
1478 adev->snd_dev_ref_cnt[snd_device]--;
1479 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480}
1481
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001482int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001483 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301485 int i, num_devices = 0;
1486 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001487 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1488
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001489 if (snd_device < SND_DEVICE_MIN ||
1490 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001491 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001492 return -EINVAL;
1493 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001494
1495 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1496 ALOGE("%s: Invalid sound device returned", __func__);
1497 return -EINVAL;
1498 }
1499
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001500 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1501 ALOGE("%s: device ref cnt is already 0", __func__);
1502 return -EINVAL;
1503 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001504
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001505 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001506
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001507
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001508 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001509 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301510
Aalique Grahame22e49102018-12-18 14:23:57 -08001511 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1512
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001513 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1514 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001515 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001516
1517 // when speaker device is disabled, reset swap.
1518 // will be renabled on usecase start
1519 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001520 } else if (platform_split_snd_device(adev->platform,
1521 snd_device,
1522 &num_devices,
1523 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301524 for (i = 0; i < num_devices; i++) {
1525 disable_snd_device(adev, new_snd_devices[i]);
1526 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001527 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001528 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001529 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001530 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001531
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001532 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301533 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001534 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001535 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001536 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001537 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301538 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001539 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301540 adev->native_playback_enabled) {
1541 ALOGD("%s: %d: napb: disabling native mode in hardware",
1542 __func__, __LINE__);
1543 audio_route_reset_and_update_path(adev->audio_route,
1544 "true-native-mode");
1545 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001546 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301547 adev->asrc_mode_enabled) {
1548 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301549 disable_asrc_mode(adev);
1550 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001551 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301552 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001553 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001554 ALOGD("%s: deinit ec ref loopback", __func__);
1555 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1556 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001557
1558 audio_extn_utils_release_snd_device(snd_device);
1559 } else {
1560 if (platform_split_snd_device(adev->platform,
1561 snd_device,
1562 &num_devices,
1563 new_snd_devices) == 0) {
1564 for (i = 0; i < num_devices; i++) {
1565 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1566 }
1567 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001568 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001570 return 0;
1571}
1572
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001573/*
1574 legend:
1575 uc - existing usecase
1576 new_uc - new usecase
1577 d1, d11, d2 - SND_DEVICE enums
1578 a1, a2 - corresponding ANDROID device enums
1579 B1, B2 - backend strings
1580
1581case 1
1582 uc->dev d1 (a1) B1
1583 new_uc->dev d1 (a1), d2 (a2) B1, B2
1584
1585 resolution: disable and enable uc->dev on d1
1586
1587case 2
1588 uc->dev d1 (a1) B1
1589 new_uc->dev d11 (a1) B1
1590
1591 resolution: need to switch uc since d1 and d11 are related
1592 (e.g. speaker and voice-speaker)
1593 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1594
1595case 3
1596 uc->dev d1 (a1) B1
1597 new_uc->dev d2 (a2) B2
1598
1599 resolution: no need to switch uc
1600
1601case 4
1602 uc->dev d1 (a1) B1
1603 new_uc->dev d2 (a2) B1
1604
1605 resolution: disable enable uc-dev on d2 since backends match
1606 we cannot enable two streams on two different devices if they
1607 share the same backend. e.g. if offload is on speaker device using
1608 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1609 using the same backend, offload must also be switched to voice-handset.
1610
1611case 5
1612 uc->dev d1 (a1) B1
1613 new_uc->dev d1 (a1), d2 (a2) B1
1614
1615 resolution: disable enable uc-dev on d2 since backends match
1616 we cannot enable two streams on two different devices if they
1617 share the same backend.
1618
1619case 6
1620 uc->dev d1 (a1) B1
1621 new_uc->dev d2 (a1) B2
1622
1623 resolution: no need to switch
1624
1625case 7
1626 uc->dev d1 (a1), d2 (a2) B1, B2
1627 new_uc->dev d1 (a1) B1
1628
1629 resolution: no need to switch
1630
Zhou Song4ba65882018-07-09 14:48:07 +08001631case 8
1632 uc->dev d1 (a1) B1
1633 new_uc->dev d11 (a1), d2 (a2) B1, B2
1634 resolution: compared to case 1, for this case, d1 and d11 are related
1635 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001636*/
1637static snd_device_t derive_playback_snd_device(void * platform,
1638 struct audio_usecase *uc,
1639 struct audio_usecase *new_uc,
1640 snd_device_t new_snd_device)
1641{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001642 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001643
1644 snd_device_t d1 = uc->out_snd_device;
1645 snd_device_t d2 = new_snd_device;
1646
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001647 list_init(&a1);
1648 list_init(&a2);
1649
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301650 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301651 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001652 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1653 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301654 break;
1655 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001656 assign_devices(&a1, &uc->stream.out->device_list);
1657 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301658 break;
1659 }
1660
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001661 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001662 if (!compare_devices(&a1, &a2) &&
1663 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001664 snd_device_t d3[2];
1665 int num_devices = 0;
1666 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001667 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001668 &num_devices,
1669 d3);
1670 if (ret < 0) {
1671 if (ret != -ENOSYS) {
1672 ALOGW("%s failed to split snd_device %d",
1673 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001674 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001675 }
1676 goto end;
1677 }
1678
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001679 if (platform_check_backends_match(d3[0], d3[1])) {
1680 return d2; // case 5
1681 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001682 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301683 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001684 // check if d1 is related to any of d3's
1685 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001686 return d1; // case 1
1687 else
1688 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001689 }
1690 } else {
1691 if (platform_check_backends_match(d1, d2)) {
1692 return d2; // case 2, 4
1693 } else {
1694 return d1; // case 6, 3
1695 }
1696 }
1697
1698end:
1699 return d2; // return whatever was calculated before.
1700}
1701
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001702static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301703 struct audio_usecase *uc_info,
1704 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001705{
1706 struct listnode *node;
1707 struct audio_usecase *usecase;
1708 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301709 snd_device_t uc_derive_snd_device;
1710 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001711 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1712 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001713 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301714 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001715 /*
1716 * This function is to make sure that all the usecases that are active on
1717 * the hardware codec backend are always routed to any one device that is
1718 * handled by the hardware codec.
1719 * For example, if low-latency and deep-buffer usecases are currently active
1720 * on speaker and out_set_parameters(headset) is received on low-latency
1721 * output, then we have to make sure deep-buffer is also switched to headset,
1722 * because of the limitation that both the devices cannot be enabled
1723 * at the same time as they share the same backend.
1724 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001725 /*
1726 * This call is to check if we need to force routing for a particular stream
1727 * If there is a backend configuration change for the device when a
1728 * new stream starts, then ADM needs to be closed and re-opened with the new
1729 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001730 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001731 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001732 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1733 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301734 /* For a2dp device reconfigure all active sessions
1735 * with new AFE encoder format based on a2dp state
1736 */
1737 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1738 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1739 audio_extn_a2dp_is_force_device_switch()) {
1740 force_routing = true;
1741 force_restart_session = true;
1742 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001743
1744 /*
1745 * Island cfg and power mode config needs to set before AFE port start.
1746 * Set force routing in case of voice device was enable before.
1747 */
1748 if (uc_info->type == VOICE_CALL &&
1749 voice_extn_is_voice_power_mode_supported() &&
1750 platform_check_and_update_island_power_status(adev->platform,
1751 uc_info,
1752 snd_device)) {
1753 force_routing = true;
1754 ALOGD("%s:becf: force routing %d for power mode supported device",
1755 __func__, force_routing);
1756 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301757 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1758
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001759 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001760 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001761 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001762 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1763 switch_device[i] = false;
1764
1765 list_for_each(node, &adev->usecase_list) {
1766 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001767
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301768 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1769 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301770 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301771 platform_get_snd_device_name(usecase->out_snd_device),
1772 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301773 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1774 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301775 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1776 usecase, uc_info, snd_device);
1777 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001778 (is_codec_backend_out_device_type(&usecase->device_list) ||
1779 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1780 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1781 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1782 is_a2dp_out_device_type(&usecase->device_list) ||
1783 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301784 ((force_restart_session) ||
1785 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301786 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1787 __func__, use_case_table[usecase->id],
1788 platform_get_snd_device_name(usecase->out_snd_device));
1789 disable_audio_route(adev, usecase);
1790 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301791 /* Enable existing usecase on derived playback device */
1792 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301793 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301794 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795 }
1796 }
1797
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301798 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1799 num_uc_to_switch);
1800
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001801 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001802 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001803
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301804 /* Make sure the previous devices to be disabled first and then enable the
1805 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001806 list_for_each(node, &adev->usecase_list) {
1807 usecase = node_to_item(node, struct audio_usecase, list);
1808 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001809 /* Check if output sound device to be switched can be split and if any
1810 of the split devices match with derived sound device */
1811 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1812 &num_devices, split_snd_devices) == 0) {
1813 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1814 for (i = 0; i < num_devices; i++) {
1815 /* Disable devices that do not match with derived sound device */
1816 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1817 disable_snd_device(adev, split_snd_devices[i]);
1818 }
1819 } else {
1820 disable_snd_device(adev, usecase->out_snd_device);
1821 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822 }
1823 }
1824
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001825 list_for_each(node, &adev->usecase_list) {
1826 usecase = node_to_item(node, struct audio_usecase, list);
1827 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001828 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1829 &num_devices, split_snd_devices) == 0) {
1830 /* Enable derived sound device only if it does not match with
1831 one of the split sound devices. This is because the matching
1832 sound device was not disabled */
1833 bool should_enable = true;
1834 for (i = 0; i < num_devices; i++) {
1835 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1836 should_enable = false;
1837 break;
1838 }
1839 }
1840 if (should_enable)
1841 enable_snd_device(adev, derive_snd_device[usecase->id]);
1842 } else {
1843 enable_snd_device(adev, derive_snd_device[usecase->id]);
1844 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001845 }
1846 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001847
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001848 /* Re-route all the usecases on the shared backend other than the
1849 specified usecase to new snd devices */
1850 list_for_each(node, &adev->usecase_list) {
1851 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301852 /* Update the out_snd_device only before enabling the audio route */
1853 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301854 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301855 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301856 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301857 use_case_table[usecase->id],
1858 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001859 /* Update voc calibration before enabling VoIP route */
1860 if (usecase->type == VOIP_CALL)
1861 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001862 usecase->out_snd_device,
1863 platform_get_input_snd_device(
1864 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301865 &uc_info->device_list,
1866 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301867 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301868 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001869 out_set_voip_volume(&usecase->stream.out->stream,
1870 usecase->stream.out->volume_l,
1871 usecase->stream.out->volume_r);
1872 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301873 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001874 }
1875 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001876 }
1877}
1878
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301879static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001880 struct audio_usecase *uc_info,
1881 snd_device_t snd_device)
1882{
1883 struct listnode *node;
1884 struct audio_usecase *usecase;
1885 bool switch_device[AUDIO_USECASE_MAX];
1886 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001887 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001888 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001889
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301890 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1891 snd_device);
1892 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301893
1894 /*
1895 * Make sure out devices is checked against out codec backend device and
1896 * also in devices against in codec backend. Checking out device against in
1897 * codec backend or vice versa causes issues.
1898 */
1899 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001900 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001901
1902 /*
1903 * Island cfg and power mode config needs to set before AFE port start.
1904 * Set force routing in case of voice device was enable before.
1905 */
1906
1907 if (uc_info->type == VOICE_CALL &&
1908 voice_extn_is_voice_power_mode_supported() &&
1909 platform_check_and_update_island_power_status(adev->platform,
1910 uc_info,
1911 snd_device)) {
1912 force_routing = true;
1913 ALOGD("%s:becf: force routing %d for power mode supported device",
1914 __func__, force_routing);
1915 }
1916
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001917 /*
1918 * This function is to make sure that all the active capture usecases
1919 * are always routed to the same input sound device.
1920 * For example, if audio-record and voice-call usecases are currently
1921 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1922 * is received for voice call then we have to make sure that audio-record
1923 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1924 * because of the limitation that two devices cannot be enabled
1925 * at the same time if they share the same backend.
1926 */
1927 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1928 switch_device[i] = false;
1929
1930 list_for_each(node, &adev->usecase_list) {
1931 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301932 /*
1933 * TODO: Enhance below condition to handle BT sco/USB multi recording
1934 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301935
1936 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1937 (usecase->in_snd_device != snd_device || force_routing));
1938 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1939 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1940 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001941 ((backend_check_cond &&
1942 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001943 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001944 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001945 is_single_device_type_equal(&usecase->device_list,
1946 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001947 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001948 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001949 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301950 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001951 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001952 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001953 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001954 switch_device[usecase->id] = true;
1955 num_uc_to_switch++;
1956 }
1957 }
1958
1959 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001960 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001961
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301962 /* Make sure the previous devices to be disabled first and then enable the
1963 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001964 list_for_each(node, &adev->usecase_list) {
1965 usecase = node_to_item(node, struct audio_usecase, list);
1966 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001967 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001968 }
1969 }
1970
1971 list_for_each(node, &adev->usecase_list) {
1972 usecase = node_to_item(node, struct audio_usecase, list);
1973 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001974 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001975 }
1976 }
1977
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001978 /* Re-route all the usecases on the shared backend other than the
1979 specified usecase to new snd devices */
1980 list_for_each(node, &adev->usecase_list) {
1981 usecase = node_to_item(node, struct audio_usecase, list);
1982 /* Update the in_snd_device only before enabling the audio route */
1983 if (switch_device[usecase->id] ) {
1984 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001985 if (usecase->type != VOICE_CALL) {
1986 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301987 if (usecase->type == VOIP_CALL) {
1988 snd_device_t voip_snd_device;
1989 voip_snd_device = platform_get_output_snd_device(adev->platform,
1990 uc_info->stream.out,
1991 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08001992 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301993 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08001994 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05301995 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05301996 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001997 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001998 }
1999 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002000 }
2001}
2002
Mingming Yin3a941d42016-02-17 18:08:05 -08002003static void reset_hdmi_sink_caps(struct stream_out *out) {
2004 int i = 0;
2005
2006 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2007 out->supported_channel_masks[i] = 0;
2008 }
2009 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2010 out->supported_formats[i] = 0;
2011 }
2012 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2013 out->supported_sample_rates[i] = 0;
2014 }
2015}
2016
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002018static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019{
Mingming Yin3a941d42016-02-17 18:08:05 -08002020 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002021 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2022 out->extconn.cs.controller,
2023 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024
Mingming Yin3a941d42016-02-17 18:08:05 -08002025 reset_hdmi_sink_caps(out);
2026
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002027 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002028 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002029 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002030 out->extconn.cs.stream);
2031 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002032 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002033 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002034 }
2035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002038 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002039 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002040 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2041 case 6:
2042 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2043 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2044 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2045 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2046 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2047 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048 break;
2049 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002050 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002051 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 break;
2053 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002054
2055 // check channel format caps
2056 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002057 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2058 out->extconn.cs.controller,
2059 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002060 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2061 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2062 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2063 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2064 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2065 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2066 }
2067
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002068 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2069 out->extconn.cs.controller,
2070 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002071 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2072 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2073 }
2074
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002075 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2076 out->extconn.cs.controller,
2077 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002078 ALOGV(":%s HDMI supports DTS format", __func__);
2079 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2080 }
2081
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002082 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2083 out->extconn.cs.controller,
2084 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002085 ALOGV(":%s HDMI supports DTS HD format", __func__);
2086 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2087 }
2088
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002089 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2090 out->extconn.cs.controller,
2091 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002092 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2093 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2094 }
2095
Mingming Yin3a941d42016-02-17 18:08:05 -08002096
2097 // check sample rate caps
2098 i = 0;
2099 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002100 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2101 out->extconn.cs.controller,
2102 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002103 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2104 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2105 }
2106 }
2107
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002108 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109}
2110
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002111static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2112 uint32_t *supported_sample_rates __unused,
2113 uint32_t max_rates __unused)
2114{
2115 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2116 supported_sample_rates,
2117 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302118 ssize_t i = 0;
2119
2120 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002121 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2122 supported_sample_rates[i]);
2123 }
2124 return count;
2125}
2126
2127static inline int read_usb_sup_channel_masks(bool is_playback,
2128 audio_channel_mask_t *supported_channel_masks,
2129 uint32_t max_masks)
2130{
2131 int channels = audio_extn_usb_get_max_channels(is_playback);
2132 int channel_count;
2133 uint32_t num_masks = 0;
2134 if (channels > MAX_HIFI_CHANNEL_COUNT)
2135 channels = MAX_HIFI_CHANNEL_COUNT;
2136
2137 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002138 // start from 2 channels as framework currently doesn't support mono.
2139 if (channels >= FCC_2) {
2140 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2141 }
2142 for (channel_count = FCC_2;
2143 channel_count <= channels && num_masks < max_masks;
2144 ++channel_count) {
2145 supported_channel_masks[num_masks++] =
2146 audio_channel_mask_for_index_assignment_from_count(channel_count);
2147 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002148 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002149 // For capture we report all supported channel masks from 1 channel up.
2150 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002151 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2152 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002153 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2154 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2155 if (channel_count <= FCC_2) {
2156 mask = audio_channel_in_mask_from_count(channel_count);
2157 supported_channel_masks[num_masks++] = mask;
2158 }
2159 const audio_channel_mask_t index_mask =
2160 audio_channel_mask_for_index_assignment_from_count(channel_count);
2161 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2162 supported_channel_masks[num_masks++] = index_mask;
2163 }
2164 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002165 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302166
vincenttewf51c94e2019-05-07 10:28:53 +08002167 for (size_t i = 0; i < num_masks; ++i) {
2168 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2169 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302170 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002171 return num_masks;
2172}
2173
2174static inline int read_usb_sup_formats(bool is_playback __unused,
2175 audio_format_t *supported_formats,
2176 uint32_t max_formats __unused)
2177{
2178 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2179 switch (bitwidth) {
2180 case 24:
2181 // XXX : usb.c returns 24 for s24 and s24_le?
2182 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2183 break;
2184 case 32:
2185 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2186 break;
2187 case 16:
2188 default :
2189 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2190 break;
2191 }
2192 ALOGV("%s: %s supported format %d", __func__,
2193 is_playback ? "P" : "C", bitwidth);
2194 return 1;
2195}
2196
2197static inline int read_usb_sup_params_and_compare(bool is_playback,
2198 audio_format_t *format,
2199 audio_format_t *supported_formats,
2200 uint32_t max_formats,
2201 audio_channel_mask_t *mask,
2202 audio_channel_mask_t *supported_channel_masks,
2203 uint32_t max_masks,
2204 uint32_t *rate,
2205 uint32_t *supported_sample_rates,
2206 uint32_t max_rates) {
2207 int ret = 0;
2208 int num_formats;
2209 int num_masks;
2210 int num_rates;
2211 int i;
2212
2213 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2214 max_formats);
2215 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2216 max_masks);
2217
2218 num_rates = read_usb_sup_sample_rates(is_playback,
2219 supported_sample_rates, max_rates);
2220
2221#define LUT(table, len, what, dflt) \
2222 for (i=0; i<len && (table[i] != what); i++); \
2223 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2224
2225 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2226 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2227 LUT(supported_sample_rates, num_rates, *rate, 0);
2228
2229#undef LUT
2230 return ret < 0 ? -EINVAL : 0; // HACK TBD
2231}
2232
Alexy Josephb1379942016-01-29 15:49:38 -08002233audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002234 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002235{
2236 struct audio_usecase *usecase;
2237 struct listnode *node;
2238
2239 list_for_each(node, &adev->usecase_list) {
2240 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002241 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002242 ALOGV("%s: usecase id %d", __func__, usecase->id);
2243 return usecase->id;
2244 }
2245 }
2246 return USECASE_INVALID;
2247}
2248
Alexy Josephb1379942016-01-29 15:49:38 -08002249struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002250 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002251{
2252 struct audio_usecase *usecase;
2253 struct listnode *node;
2254
2255 list_for_each(node, &adev->usecase_list) {
2256 usecase = node_to_item(node, struct audio_usecase, list);
2257 if (usecase->id == uc_id)
2258 return usecase;
2259 }
2260 return NULL;
2261}
2262
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302263/*
2264 * is a true native playback active
2265 */
2266bool audio_is_true_native_stream_active(struct audio_device *adev)
2267{
2268 bool active = false;
2269 int i = 0;
2270 struct listnode *node;
2271
2272 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2273 ALOGV("%s:napb: not in true mode or non hdphones device",
2274 __func__);
2275 active = false;
2276 goto exit;
2277 }
2278
2279 list_for_each(node, &adev->usecase_list) {
2280 struct audio_usecase *uc;
2281 uc = node_to_item(node, struct audio_usecase, list);
2282 struct stream_out *curr_out =
2283 (struct stream_out*) uc->stream.out;
2284
2285 if (curr_out && PCM_PLAYBACK == uc->type) {
2286 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2287 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2288 uc->id, curr_out->sample_rate,
2289 curr_out->bit_width,
2290 platform_get_snd_device_name(uc->out_snd_device));
2291
2292 if (is_offload_usecase(uc->id) &&
2293 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2294 active = true;
2295 ALOGD("%s:napb:native stream detected", __func__);
2296 }
2297 }
2298 }
2299exit:
2300 return active;
2301}
2302
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002303uint32_t adev_get_dsp_bit_width_enforce_mode()
2304{
2305 if (adev == NULL) {
2306 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2307 return 0;
2308 }
2309 return adev->dsp_bit_width_enforce_mode;
2310}
2311
2312static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2313{
2314 char value[PROPERTY_VALUE_MAX];
2315 int trial;
2316 uint32_t dsp_bit_width_enforce_mode = 0;
2317
2318 if (!mixer) {
2319 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2320 __func__);
2321 return 0;
2322 }
2323
2324 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2325 value, NULL) > 0) {
2326 trial = atoi(value);
2327 switch (trial) {
2328 case 16:
2329 dsp_bit_width_enforce_mode = 16;
2330 break;
2331 case 24:
2332 dsp_bit_width_enforce_mode = 24;
2333 break;
2334 case 32:
2335 dsp_bit_width_enforce_mode = 32;
2336 break;
2337 default:
2338 dsp_bit_width_enforce_mode = 0;
2339 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2340 break;
2341 }
2342 }
2343
2344 return dsp_bit_width_enforce_mode;
2345}
2346
2347static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2348 uint32_t enforce_mode,
2349 bool enable)
2350{
2351 struct mixer_ctl *ctl = NULL;
2352 const char *mixer_ctl_name = "ASM Bit Width";
2353 uint32_t asm_bit_width_mode = 0;
2354
2355 if (enforce_mode == 0) {
2356 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2357 return;
2358 }
2359
2360 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2361 if (!ctl) {
2362 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2363 __func__, mixer_ctl_name);
2364 return;
2365 }
2366
2367 if (enable)
2368 asm_bit_width_mode = enforce_mode;
2369 else
2370 asm_bit_width_mode = 0;
2371
2372 ALOGV("%s DSP bit width feature status is %d width=%d",
2373 __func__, enable, asm_bit_width_mode);
2374 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2375 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2376 asm_bit_width_mode);
2377
2378 return;
2379}
2380
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302381/*
2382 * if native DSD playback active
2383 */
2384bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2385{
2386 bool active = false;
2387 struct listnode *node = NULL;
2388 struct audio_usecase *uc = NULL;
2389 struct stream_out *curr_out = NULL;
2390
2391 list_for_each(node, &adev->usecase_list) {
2392 uc = node_to_item(node, struct audio_usecase, list);
2393 curr_out = (struct stream_out*) uc->stream.out;
2394
2395 if (curr_out && PCM_PLAYBACK == uc->type &&
2396 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2397 active = true;
2398 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302399 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302400 }
2401 }
2402 return active;
2403}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302404
2405static bool force_device_switch(struct audio_usecase *usecase)
2406{
2407 bool ret = false;
2408 bool is_it_true_mode = false;
2409
Zhou Song30f2c3e2018-02-08 14:02:15 +08002410 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302411 usecase->type == TRANSCODE_LOOPBACK_RX ||
2412 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002413 return false;
2414 }
2415
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002416 if(usecase->stream.out == NULL) {
2417 ALOGE("%s: stream.out is NULL", __func__);
2418 return false;
2419 }
2420
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302421 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002422 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002423 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2424 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302425 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2426 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2427 (!is_it_true_mode && adev->native_playback_enabled)){
2428 ret = true;
2429 ALOGD("napb: time to toggle native mode");
2430 }
2431 }
2432
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302433 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302434 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2435 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002436 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302437 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302438 ALOGD("Force a2dp device switch to update new encoder config");
2439 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002440 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302441
Florian Pfister1a84f312018-07-19 14:38:18 +02002442 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302443 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2444 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002445 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302446 return ret;
2447}
2448
Aalique Grahame22e49102018-12-18 14:23:57 -08002449static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2450{
2451 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2452}
2453
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302454bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2455{
2456 bool ret=false;
2457 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002458 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2459 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302460 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2461 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002462 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302463 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002464 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2465 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302466 ret = true;
2467
2468 return ret;
2469}
2470
2471bool is_a2dp_device(snd_device_t out_snd_device)
2472{
2473 bool ret=false;
2474 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2475 ret = true;
2476
2477 return ret;
2478}
2479
2480bool is_bt_soc_on(struct audio_device *adev)
2481{
2482 struct mixer_ctl *ctl;
2483 char *mixer_ctl_name = "BT SOC status";
2484 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2485 bool bt_soc_status = true;
2486 if (!ctl) {
2487 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2488 __func__, mixer_ctl_name);
2489 /*This is to ensure we dont break targets which dont have the kernel change*/
2490 return true;
2491 }
2492 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2493 ALOGD("BT SOC status: %d",bt_soc_status);
2494 return bt_soc_status;
2495}
2496
Zhou Song331c8e52019-08-26 14:16:12 +08002497static int configure_btsco_sample_rate(snd_device_t snd_device)
2498{
2499 struct mixer_ctl *ctl = NULL;
2500 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2501 char *rate_str = NULL;
2502 bool is_rx_dev = true;
2503
2504 if (is_btsco_device(snd_device, snd_device)) {
2505 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2506 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2507 if (!ctl_sr_tx || !ctl_sr_rx) {
2508 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2509 if (!ctl_sr)
2510 return -ENOSYS;
2511 }
2512
2513 switch (snd_device) {
2514 case SND_DEVICE_OUT_BT_SCO:
2515 rate_str = "KHZ_8";
2516 break;
2517 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2518 case SND_DEVICE_IN_BT_SCO_MIC:
2519 rate_str = "KHZ_8";
2520 is_rx_dev = false;
2521 break;
2522 case SND_DEVICE_OUT_BT_SCO_WB:
2523 rate_str = "KHZ_16";
2524 break;
2525 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2526 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2527 rate_str = "KHZ_16";
2528 is_rx_dev = false;
2529 break;
2530 default:
2531 return 0;
2532 }
2533
2534 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2535 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2536 return -ENOSYS;
2537 }
2538 return 0;
2539}
2540
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302541int out_standby_l(struct audio_stream *stream);
2542
Eric Laurent637e2d42018-11-15 12:24:31 -08002543struct stream_in *adev_get_active_input(const struct audio_device *adev)
2544{
2545 struct listnode *node;
2546 struct stream_in *last_active_in = NULL;
2547
2548 /* Get last added active input.
2549 * TODO: We may use a priority mechanism to pick highest priority active source */
2550 list_for_each(node, &adev->usecase_list)
2551 {
2552 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2553 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2554 last_active_in = usecase->stream.in;
2555 }
2556
2557 return last_active_in;
2558}
2559
2560struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2561{
2562 struct listnode *node;
2563
2564 /* First check active inputs with voice communication source and then
2565 * any input if audio mode is in communication */
2566 list_for_each(node, &adev->usecase_list)
2567 {
2568 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2569 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2570 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2571 return usecase->stream.in;
2572 }
2573 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2574 return adev_get_active_input(adev);
2575
2576 return NULL;
2577}
2578
Carter Hsu2e429db2019-05-14 18:50:52 +08002579/*
2580 * Aligned with policy.h
2581 */
2582static inline int source_priority(int inputSource)
2583{
2584 switch (inputSource) {
2585 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2586 return 9;
2587 case AUDIO_SOURCE_CAMCORDER:
2588 return 8;
2589 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2590 return 7;
2591 case AUDIO_SOURCE_UNPROCESSED:
2592 return 6;
2593 case AUDIO_SOURCE_MIC:
2594 return 5;
2595 case AUDIO_SOURCE_ECHO_REFERENCE:
2596 return 4;
2597 case AUDIO_SOURCE_FM_TUNER:
2598 return 3;
2599 case AUDIO_SOURCE_VOICE_RECOGNITION:
2600 return 2;
2601 case AUDIO_SOURCE_HOTWORD:
2602 return 1;
2603 default:
2604 break;
2605 }
2606 return 0;
2607}
2608
2609static struct stream_in *get_priority_input(struct audio_device *adev)
2610{
2611 struct listnode *node;
2612 struct audio_usecase *usecase;
2613 int last_priority = 0, priority;
2614 struct stream_in *priority_in = NULL;
2615 struct stream_in *in;
2616
2617 list_for_each(node, &adev->usecase_list) {
2618 usecase = node_to_item(node, struct audio_usecase, list);
2619 if (usecase->type == PCM_CAPTURE) {
2620 in = usecase->stream.in;
2621 if (!in)
2622 continue;
2623 priority = source_priority(in->source);
2624
2625 if (priority > last_priority) {
2626 last_priority = priority;
2627 priority_in = in;
2628 }
2629 }
2630 }
2631 return priority_in;
2632}
2633
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002634int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002636 snd_device_t out_snd_device = SND_DEVICE_NONE;
2637 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002638 struct audio_usecase *usecase = NULL;
2639 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002640 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002641 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302642 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002643 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002644 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302646 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2647
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002648 usecase = get_usecase_from_list(adev, uc_id);
2649 if (usecase == NULL) {
2650 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2651 return -EINVAL;
2652 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002654 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002655 (usecase->type == VOIP_CALL) ||
2656 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302657 if(usecase->stream.out == NULL) {
2658 ALOGE("%s: stream.out is NULL", __func__);
2659 return -EINVAL;
2660 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002661 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002662 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2663 uc_id);
2664 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2665 uc_id);
2666 } else {
2667 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302668 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002669 in_snd_device = platform_get_input_snd_device(adev->platform,
2670 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302671 &usecase->stream.out->device_list,
2672 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002673 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002674 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302675 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302676 if (usecase->stream.inout == NULL) {
2677 ALOGE("%s: stream.inout is NULL", __func__);
2678 return -EINVAL;
2679 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002680 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302681 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2682 stream_out.format = usecase->stream.inout->out_config.format;
2683 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302684 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002685 assign_devices(&usecase->device_list,
2686 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302687 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2688 if (usecase->stream.inout == NULL) {
2689 ALOGE("%s: stream.inout is NULL", __func__);
2690 return -EINVAL;
2691 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302692 struct listnode out_devices;
2693 list_init(&out_devices);
2694 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2695 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002696 assign_devices(&usecase->device_list,
2697 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002698 } else {
2699 /*
2700 * If the voice call is active, use the sound devices of voice call usecase
2701 * so that it would not result any device switch. All the usecases will
2702 * be switched to new device when select_devices() is called for voice call
2703 * usecase. This is to avoid switching devices for voice call when
2704 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002705 * choose voice call device only if the use case device is
2706 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002707 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002708 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002709 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002710 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002711 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2712 is_codec_backend_out_device_type(&usecase->device_list)) ||
2713 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2714 is_codec_backend_in_device_type(&usecase->device_list)) ||
2715 is_single_device_type_equal(&vc_usecase->device_list,
2716 AUDIO_DEVICE_OUT_HEARING_AID) ||
2717 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002718 AUDIO_DEVICE_IN_VOICE_CALL) ||
2719 (is_single_device_type_equal(&usecase->device_list,
2720 AUDIO_DEVICE_IN_USB_HEADSET) &&
2721 is_single_device_type_equal(&vc_usecase->device_list,
2722 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002723 in_snd_device = vc_usecase->in_snd_device;
2724 out_snd_device = vc_usecase->out_snd_device;
2725 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002726 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002727 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002728 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002729 if ((voip_usecase != NULL) &&
2730 (usecase->type == PCM_PLAYBACK) &&
2731 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002732 out_snd_device_backend_match = platform_check_backends_match(
2733 voip_usecase->out_snd_device,
2734 platform_get_output_snd_device(
2735 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302736 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002737 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002738 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2739 (is_codec_backend_out_device_type(&usecase->device_list) ||
2740 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002741 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002742 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002743 in_snd_device = voip_usecase->in_snd_device;
2744 out_snd_device = voip_usecase->out_snd_device;
2745 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002746 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002747 hfp_ucid = audio_extn_hfp_get_usecase();
2748 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002749 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002750 in_snd_device = hfp_usecase->in_snd_device;
2751 out_snd_device = hfp_usecase->out_snd_device;
2752 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002753 }
2754 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302755 if (usecase->stream.out == NULL) {
2756 ALOGE("%s: stream.out is NULL", __func__);
2757 return -EINVAL;
2758 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002759 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002760 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002761 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002762 struct stream_out *voip_out = adev->primary_output;
2763 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002764 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002765 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2766 else
2767 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302768 usecase->stream.out,
2769 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002770 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002771
Eric Laurent637e2d42018-11-15 12:24:31 -08002772 if (voip_usecase)
2773 voip_out = voip_usecase->stream.out;
2774
2775 if (usecase->stream.out == voip_out && voip_in != NULL)
2776 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002777 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002778 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302779 if (usecase->stream.in == NULL) {
2780 ALOGE("%s: stream.in is NULL", __func__);
2781 return -EINVAL;
2782 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002783 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002784 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002785 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002786 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002787 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002788 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002789
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002790 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002791 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002792 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2793 USECASE_AUDIO_PLAYBACK_VOIP);
2794
Carter Hsu2e429db2019-05-14 18:50:52 +08002795 usecase->stream.in->enable_ec_port = false;
2796
Zhou Song62ea0282020-03-22 19:53:01 +08002797 bool is_ha_usecase = adev->ha_proxy_enable ?
2798 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2799 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2800 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002801 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002802 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002803 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002804 } else if (adev->primary_output &&
2805 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002806 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002807 } else {
2808 /* forcing speaker o/p device to get matching i/p pair
2809 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002810 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002811 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002812 priority_in = voip_in;
2813 } else {
2814 /* get the input with the highest priority source*/
2815 priority_in = get_priority_input(adev);
2816
2817 if (!priority_in)
2818 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002819 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002820
Eric Laurent637e2d42018-11-15 12:24:31 -08002821 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002822 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302823 &out_devices,
2824 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002825 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002826 }
2827 }
2828
2829 if (out_snd_device == usecase->out_snd_device &&
2830 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302831
2832 if (!force_device_switch(usecase))
2833 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834 }
2835
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002836 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002837 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002838 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002839 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2840 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302841 }
2842
Aalique Grahame22e49102018-12-18 14:23:57 -08002843 if (out_snd_device != SND_DEVICE_NONE &&
2844 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2845 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2846 __func__,
2847 use_case_table[uc_id],
2848 adev->last_logged_snd_device[uc_id][0],
2849 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2850 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2851 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2852 -1,
2853 out_snd_device,
2854 platform_get_snd_device_name(out_snd_device),
2855 platform_get_snd_device_acdb_id(out_snd_device));
2856 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2857 }
2858 if (in_snd_device != SND_DEVICE_NONE &&
2859 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2860 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2861 __func__,
2862 use_case_table[uc_id],
2863 adev->last_logged_snd_device[uc_id][1],
2864 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2865 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2866 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2867 -1,
2868 in_snd_device,
2869 platform_get_snd_device_name(in_snd_device),
2870 platform_get_snd_device_acdb_id(in_snd_device));
2871 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2872 }
2873
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 /*
2876 * Limitation: While in call, to do a device switch we need to disable
2877 * and enable both RX and TX devices though one of them is same as current
2878 * device.
2879 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002880 if ((usecase->type == VOICE_CALL) &&
2881 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2882 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002883 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002884 }
2885
2886 if (((usecase->type == VOICE_CALL) ||
2887 (usecase->type == VOIP_CALL)) &&
2888 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2889 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302890 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002891 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002892 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002893
2894 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302895 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002896 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002897 }
2898
Aalique Grahame22e49102018-12-18 14:23:57 -08002899 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2900 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002901 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302902 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002903 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2904 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2905 else
2906 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302907 }
2908
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002909 /* Disable current sound devices */
2910 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002911 disable_audio_route(adev, usecase);
2912 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913 }
2914
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002915 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002916 disable_audio_route(adev, usecase);
2917 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918 }
2919
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002920 /* Applicable only on the targets that has external modem.
2921 * New device information should be sent to modem before enabling
2922 * the devices to reduce in-call device switch time.
2923 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002924 if ((usecase->type == VOICE_CALL) &&
2925 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2926 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002927 status = platform_switch_voice_call_enable_device_config(adev->platform,
2928 out_snd_device,
2929 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002930 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002931
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002932 /* Enable new sound devices */
2933 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002934 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302935 if (platform_check_codec_asrc_support(adev->platform))
2936 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002937 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938 }
2939
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002940 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302941 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002942 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002943 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002944
Avinash Vaish71a8b972014-07-24 15:36:33 +05302945 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002946 status = platform_switch_voice_call_device_post(adev->platform,
2947 out_snd_device,
2948 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302949 enable_audio_route_for_voice_usecases(adev, usecase);
2950 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002951
sangwoo170731f2013-06-08 15:36:36 +09002952 usecase->in_snd_device = in_snd_device;
2953 usecase->out_snd_device = out_snd_device;
2954
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302955 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2956 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302957 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002958 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002959 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002960 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2961 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2962 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2963 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2964 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2965 /*
2966 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2967 * configured device sample rate, if not update the COPP rate to be equal to the
2968 * device sample rate, else open COPP at stream sample rate
2969 */
2970 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2971 usecase->stream.out->sample_rate,
2972 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302973 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302974 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2975 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302976 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002977 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2978 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2979 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2980 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002981 }
2982 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002983
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002984 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002985
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002986 /* If input stream is already running then effect needs to be
2987 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002988 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002989 check_and_enable_effect(adev);
2990
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002991 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002992 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302993 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002994 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2995
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002996 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302997 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002998 voice_extn_compress_voip_is_started(adev))
2999 voice_set_sidetone(adev, out_snd_device, true);
3000 }
3001
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003002 /* Applicable only on the targets that has external modem.
3003 * Enable device command should be sent to modem only after
3004 * enabling voice call mixer controls
3005 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003006 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003007 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3008 out_snd_device,
3009 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303010
3011 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003012 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303013 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003014 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303015 if (is_bt_soc_on(adev) == false){
3016 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003017 if (in->pcm != NULL)
3018 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303019 }
3020 }
3021 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3022 && usecase->stream.out->started) {
3023 if (is_bt_soc_on(adev) == false) {
3024 ALOGD("BT SCO/A2DP disconnected while in connection");
3025 out_standby_l(&usecase->stream.out->stream.common);
3026 }
3027 }
3028 } else if ((usecase->stream.out != NULL) &&
3029 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303030 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3031 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003032 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303033 usecase->stream.out->started) {
3034 if (is_bt_soc_on(adev) == false) {
3035 ALOGD("BT SCO/A2dp disconnected while in connection");
3036 out_standby_l(&usecase->stream.out->stream.common);
3037 }
3038 }
3039 }
3040
Yung Ti Su70cb8242018-06-22 17:38:47 +08003041 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003042 struct stream_out *voip_out = voip_usecase->stream.out;
3043 audio_extn_utils_send_app_type_gain(adev,
3044 voip_out->app_type_cfg.app_type,
3045 &voip_out->app_type_cfg.gain[0]);
3046 }
3047
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303048 ALOGD("%s: done",__func__);
3049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 return status;
3051}
3052
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053static int stop_input_stream(struct stream_in *in)
3054{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303055 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303057
3058 if (in == NULL) {
3059 ALOGE("%s: stream_in ptr is NULL", __func__);
3060 return -EINVAL;
3061 }
3062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003064 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065
Eric Laurent994a6932013-07-17 11:51:42 -07003066 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003067 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 uc_info = get_usecase_from_list(adev, in->usecase);
3069 if (uc_info == NULL) {
3070 ALOGE("%s: Could not find the usecase (%d) in the list",
3071 __func__, in->usecase);
3072 return -EINVAL;
3073 }
3074
Carter Hsu2e429db2019-05-14 18:50:52 +08003075 priority_in = get_priority_input(adev);
3076
Derek Chenea197282019-01-07 17:35:01 -08003077 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3078 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003079
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003080 /* Close in-call recording streams */
3081 voice_check_and_stop_incall_rec_usecase(adev, in);
3082
Eric Laurent150dbfe2013-02-27 14:31:02 -08003083 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003084 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003085
3086 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003087 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003089 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303090 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3091
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003092 list_remove(&uc_info->list);
3093 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094
Carter Hsu2e429db2019-05-14 18:50:52 +08003095 if (priority_in == in) {
3096 priority_in = get_priority_input(adev);
3097 if (priority_in)
3098 select_devices(adev, priority_in->usecase);
3099 }
3100
Vatsal Buchac09ae062018-11-14 13:25:08 +05303101 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003102 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103 return ret;
3104}
3105
3106int start_input_stream(struct stream_in *in)
3107{
3108 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003109 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303111
3112 if (in == NULL) {
3113 ALOGE("%s: stream_in ptr is NULL", __func__);
3114 return -EINVAL;
3115 }
3116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003118 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003119 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120
Mingming Yin2664a5b2015-09-03 10:53:11 -07003121 if (get_usecase_from_list(adev, usecase) == NULL)
3122 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303123 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3124 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003125
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303126 if (CARD_STATUS_OFFLINE == in->card_status||
3127 CARD_STATUS_OFFLINE == adev->card_status) {
3128 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303129 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303130 goto error_config;
3131 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303132
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003133 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303134 if (!adev->bt_sco_on) {
3135 ALOGE("%s: SCO profile is not ready, return error", __func__);
3136 ret = -EIO;
3137 goto error_config;
3138 }
3139 }
3140
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003141 /* Check if source matches incall recording usecase criteria */
3142 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3143 if (ret)
3144 goto error_config;
3145 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003146 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3147
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303148 if (audio_extn_cin_attached_usecase(in))
3149 audio_extn_cin_acquire_usecase(in);
3150
Mingming Yin2664a5b2015-09-03 10:53:11 -07003151 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3152 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3153 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003154 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003155 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003156
Eric Laurentb23d5282013-05-14 15:27:20 -07003157 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 if (in->pcm_device_id < 0) {
3159 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3160 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003161 ret = -EINVAL;
3162 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003166
3167 if (!uc_info) {
3168 ret = -ENOMEM;
3169 goto error_config;
3170 }
3171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 uc_info->id = in->usecase;
3173 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003174 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003175 list_init(&uc_info->device_list);
3176 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003177 uc_info->in_snd_device = SND_DEVICE_NONE;
3178 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003180 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003181 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303182 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3183 adev->perf_lock_opts,
3184 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003185 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186
Derek Chenea197282019-01-07 17:35:01 -08003187 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3188 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003189
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303190 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3191
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303192 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303193 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303194 if (ret)
3195 goto error_open;
3196 else
3197 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003198 }
3199
Haynes Mathew George16081042017-05-31 17:16:49 -07003200 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003201 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003202 ALOGE("%s: pcm stream not ready", __func__);
3203 goto error_open;
3204 }
3205 ret = pcm_start(in->pcm);
3206 if (ret < 0) {
3207 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3208 goto error_open;
3209 }
3210 } else {
3211 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3212 unsigned int pcm_open_retry_count = 0;
3213
Zhou Song62ea0282020-03-22 19:53:01 +08003214 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3215 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003216 flags |= PCM_MMAP | PCM_NOIRQ;
3217 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3218 } else if (in->realtime) {
3219 flags |= PCM_MMAP | PCM_NOIRQ;
3220 }
3221
Garmond Leunge2433c32017-09-28 21:51:22 -07003222 if (audio_extn_ffv_get_stream() == in) {
3223 ALOGD("%s: ffv stream, update pcm config", __func__);
3224 audio_extn_ffv_update_pcm_config(&config);
3225 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003226 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3227 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3228
3229 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003230 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003231 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003232 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003233 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303234 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303235 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3236 adev->card_status = CARD_STATUS_OFFLINE;
3237 in->card_status = CARD_STATUS_OFFLINE;
3238 ret = -EIO;
3239 goto error_open;
3240 }
3241
Haynes Mathew George16081042017-05-31 17:16:49 -07003242 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3243 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3244 if (in->pcm != NULL) {
3245 pcm_close(in->pcm);
3246 in->pcm = NULL;
3247 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003248 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003249 ret = -EIO;
3250 goto error_open;
3251 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003252 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003253 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3254 continue;
3255 }
3256 break;
3257 }
3258
3259 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003260 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003261 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003262 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003263 if (ret < 0) {
3264 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3265 pcm_close(in->pcm);
3266 in->pcm = NULL;
3267 goto error_open;
3268 }
3269 register_in_stream(in);
3270 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003271 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003272 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003273 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003274 if (ret < 0) {
3275 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003276 pcm_close(in->pcm);
3277 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003278 goto error_open;
3279 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003280 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003281 }
3282
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003283 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003284 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3285 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003286
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003287 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303288 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3289
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303290done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003291 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303292 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003293 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303294 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003295 return ret;
3296
3297error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003298 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303299 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003301
Eric Laurentc8400632013-02-14 19:04:54 -08003302error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303303 /*
3304 * sleep 50ms to allow sufficient time for kernel
3305 * drivers to recover incases like SSR.
3306 */
3307 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003308 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303309 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003310 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311}
3312
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003313void lock_input_stream(struct stream_in *in)
3314{
3315 pthread_mutex_lock(&in->pre_lock);
3316 pthread_mutex_lock(&in->lock);
3317 pthread_mutex_unlock(&in->pre_lock);
3318}
3319
3320void lock_output_stream(struct stream_out *out)
3321{
3322 pthread_mutex_lock(&out->pre_lock);
3323 pthread_mutex_lock(&out->lock);
3324 pthread_mutex_unlock(&out->pre_lock);
3325}
3326
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003327/* must be called with out->lock locked */
3328static int send_offload_cmd_l(struct stream_out* out, int command)
3329{
3330 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3331
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003332 if (!cmd) {
3333 ALOGE("failed to allocate mem for command 0x%x", command);
3334 return -ENOMEM;
3335 }
3336
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003337 ALOGVV("%s %d", __func__, command);
3338
3339 cmd->cmd = command;
3340 list_add_tail(&out->offload_cmd_list, &cmd->node);
3341 pthread_cond_signal(&out->offload_cond);
3342 return 0;
3343}
3344
3345/* must be called iwth out->lock locked */
3346static void stop_compressed_output_l(struct stream_out *out)
3347{
3348 out->offload_state = OFFLOAD_STATE_IDLE;
3349 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003350 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003351 if (out->compr != NULL) {
3352 compress_stop(out->compr);
3353 while (out->offload_thread_blocked) {
3354 pthread_cond_wait(&out->cond, &out->lock);
3355 }
3356 }
3357}
3358
Varun Balaraje49253e2017-07-06 19:48:56 +05303359bool is_interactive_usecase(audio_usecase_t uc_id)
3360{
3361 unsigned int i;
3362 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3363 if (uc_id == interactive_usecases[i])
3364 return true;
3365 }
3366 return false;
3367}
3368
3369static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3370{
3371 audio_usecase_t ret_uc = USECASE_INVALID;
3372 unsigned int intract_uc_index;
3373 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3374
3375 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3376 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3377 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3378 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3379 ret_uc = interactive_usecases[intract_uc_index];
3380 break;
3381 }
3382 }
3383
3384 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3385 return ret_uc;
3386}
3387
3388static void free_interactive_usecase(struct audio_device *adev,
3389 audio_usecase_t uc_id)
3390{
3391 unsigned int interact_uc_index;
3392 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3393
3394 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3395 if (interactive_usecases[interact_uc_index] == uc_id) {
3396 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3397 break;
3398 }
3399 }
3400 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3401}
3402
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003403bool is_offload_usecase(audio_usecase_t uc_id)
3404{
3405 unsigned int i;
3406 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3407 if (uc_id == offload_usecases[i])
3408 return true;
3409 }
3410 return false;
3411}
3412
Dhananjay Kumarac341582017-02-23 23:42:25 +05303413static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003414{
vivek mehta446c3962015-09-14 10:57:35 -07003415 audio_usecase_t ret_uc = USECASE_INVALID;
3416 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003417 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003418 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303419 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003420 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3421 else
3422 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003423
vivek mehta446c3962015-09-14 10:57:35 -07003424 pthread_mutex_lock(&adev->lock);
3425 if (get_usecase_from_list(adev, ret_uc) != NULL)
3426 ret_uc = USECASE_INVALID;
3427 pthread_mutex_unlock(&adev->lock);
3428
3429 return ret_uc;
3430 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003431
3432 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003433 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3434 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3435 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3436 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003437 break;
3438 }
3439 }
vivek mehta446c3962015-09-14 10:57:35 -07003440
3441 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3442 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003443}
3444
3445static void free_offload_usecase(struct audio_device *adev,
3446 audio_usecase_t uc_id)
3447{
vivek mehta446c3962015-09-14 10:57:35 -07003448 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003449 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003450
3451 if (!adev->multi_offload_enable)
3452 return;
3453
3454 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3455 if (offload_usecases[offload_uc_index] == uc_id) {
3456 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003457 break;
3458 }
3459 }
3460 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3461}
3462
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003463static void *offload_thread_loop(void *context)
3464{
3465 struct stream_out *out = (struct stream_out *) context;
3466 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003467 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003468
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003469 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003470 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003471 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3472
3473 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003474 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003475 out->offload_state = OFFLOAD_STATE_IDLE;
3476 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003477 for (;;) {
3478 struct offload_cmd *cmd = NULL;
3479 stream_callback_event_t event;
3480 bool send_callback = false;
3481
3482 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3483 __func__, list_empty(&out->offload_cmd_list),
3484 out->offload_state);
3485 if (list_empty(&out->offload_cmd_list)) {
3486 ALOGV("%s SLEEPING", __func__);
3487 pthread_cond_wait(&out->offload_cond, &out->lock);
3488 ALOGV("%s RUNNING", __func__);
3489 continue;
3490 }
3491
3492 item = list_head(&out->offload_cmd_list);
3493 cmd = node_to_item(item, struct offload_cmd, node);
3494 list_remove(item);
3495
3496 ALOGVV("%s STATE %d CMD %d out->compr %p",
3497 __func__, out->offload_state, cmd->cmd, out->compr);
3498
3499 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3500 free(cmd);
3501 break;
3502 }
3503
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003504 // allow OFFLOAD_CMD_ERROR reporting during standby
3505 // this is needed to handle failures during compress_open
3506 // Note however that on a pause timeout, the stream is closed
3507 // and no offload usecase will be active. Therefore this
3508 // special case is needed for compress_open failures alone
3509 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3510 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003511 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003512 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003513 pthread_cond_signal(&out->cond);
3514 continue;
3515 }
3516 out->offload_thread_blocked = true;
3517 pthread_mutex_unlock(&out->lock);
3518 send_callback = false;
3519 switch(cmd->cmd) {
3520 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003521 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003522 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003523 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003524 send_callback = true;
3525 event = STREAM_CBK_EVENT_WRITE_READY;
3526 break;
3527 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003528 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303529 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003530 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303531 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003532 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303533 if (ret < 0)
3534 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303535 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303536 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003537 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003538 else
3539 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003540 if (-ENETRESET != ret && !(-EINTR == ret &&
3541 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303542 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303543 pthread_mutex_lock(&out->lock);
3544 out->send_new_metadata = 1;
3545 out->send_next_track_params = true;
3546 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303547 event = STREAM_CBK_EVENT_DRAIN_READY;
3548 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3549 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303550 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003551 break;
3552 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003553 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003554 ret = compress_drain(out->compr);
3555 ALOGD("copl(%p):out of compress_drain", out);
3556 // EINTR check avoids drain interruption due to SSR
3557 if (-ENETRESET != ret && !(-EINTR == ret &&
3558 CARD_STATUS_OFFLINE == out->card_status)) {
3559 send_callback = true;
3560 event = STREAM_CBK_EVENT_DRAIN_READY;
3561 } else
3562 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003563 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303564 case OFFLOAD_CMD_ERROR:
3565 ALOGD("copl(%p): sending error callback to AF", out);
3566 send_callback = true;
3567 event = STREAM_CBK_EVENT_ERROR;
3568 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003569 default:
3570 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3571 break;
3572 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003573 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003574 out->offload_thread_blocked = false;
3575 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003576 if (send_callback && out->client_callback) {
3577 ALOGVV("%s: sending client_callback event %d", __func__, event);
3578 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003579 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003580 free(cmd);
3581 }
3582
3583 pthread_cond_signal(&out->cond);
3584 while (!list_empty(&out->offload_cmd_list)) {
3585 item = list_head(&out->offload_cmd_list);
3586 list_remove(item);
3587 free(node_to_item(item, struct offload_cmd, node));
3588 }
3589 pthread_mutex_unlock(&out->lock);
3590
3591 return NULL;
3592}
3593
3594static int create_offload_callback_thread(struct stream_out *out)
3595{
3596 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3597 list_init(&out->offload_cmd_list);
3598 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3599 offload_thread_loop, out);
3600 return 0;
3601}
3602
3603static int destroy_offload_callback_thread(struct stream_out *out)
3604{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003605 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003606 stop_compressed_output_l(out);
3607 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3608
3609 pthread_mutex_unlock(&out->lock);
3610 pthread_join(out->offload_thread, (void **) NULL);
3611 pthread_cond_destroy(&out->offload_cond);
3612
3613 return 0;
3614}
3615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616static int stop_output_stream(struct stream_out *out)
3617{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303618 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619 struct audio_usecase *uc_info;
3620 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003621 bool has_voip_usecase =
3622 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623
Eric Laurent994a6932013-07-17 11:51:42 -07003624 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003625 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 uc_info = get_usecase_from_list(adev, out->usecase);
3627 if (uc_info == NULL) {
3628 ALOGE("%s: Could not find the usecase (%d) in the list",
3629 __func__, out->usecase);
3630 return -EINVAL;
3631 }
3632
Derek Chenea197282019-01-07 17:35:01 -08003633 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3634 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003635
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003636 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303637 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003638 if (adev->visualizer_stop_output != NULL)
3639 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003640
3641 audio_extn_dts_remove_state_notifier_node(out->usecase);
3642
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003643 if (adev->offload_effects_stop_output != NULL)
3644 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003645 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3646 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3647 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003648 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003649
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003650 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3651 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003652 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003653 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003654
Eric Laurent150dbfe2013-02-27 14:31:02 -08003655 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003656 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003657
3658 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003659 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660
Aalique Grahame22e49102018-12-18 14:23:57 -08003661 audio_extn_extspk_update(adev->extspk);
3662
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003663 if (is_offload_usecase(out->usecase)) {
3664 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3665 adev->dsp_bit_width_enforce_mode,
3666 false);
3667 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003668 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003669 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3670 false);
3671
3672 if (ret != 0)
3673 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3674 /* default service interval was successfully updated,
3675 reopen USB backend with new service interval */
3676 ret = 0;
3677 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003678
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003679 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303680 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003681 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303682 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003683 ALOGV("Disable passthrough , reset mixer to pcm");
3684 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003685#ifdef AUDIO_GKI_ENABLED
3686 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3687 out->compr_config.codec->reserved[0] = 0;
3688#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003689 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003690#endif
Mingming Yin21854652016-04-13 11:54:02 -07003691 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003692 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3693 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003694
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303695 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003696 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303697 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303698
Manish Dewangan21a850a2017-08-14 12:03:55 +05303699 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003700 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3701 if (ret < 0)
3702 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3703 }
3704
juyuchen2d415992018-11-16 14:15:16 +08003705 /* 1) media + voip output routing to handset must route media back to
3706 speaker when voip stops.
3707 2) trigger voip input to reroute when voip output changes to
3708 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003709 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003710 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003711 struct listnode *node;
3712 struct audio_usecase *usecase;
3713 list_for_each(node, &adev->usecase_list) {
3714 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003715 if ((usecase->type == PCM_CAPTURE &&
3716 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3717 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003718 continue;
3719
3720 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3721 __func__, usecase->id, use_case_table[usecase->id],
3722 out->usecase, use_case_table[out->usecase]);
3723 select_devices(adev, usecase->id);
3724 }
3725 }
3726
Garmond Leung5fd0b552018-04-17 11:56:12 -07003727 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003728 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 return ret;
3730}
3731
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003732struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3733 unsigned int flags, unsigned int pcm_open_retry_count,
3734 struct pcm_config *config)
3735{
3736 struct pcm* pcm = NULL;
3737
3738 while (1) {
3739 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3740 if (pcm == NULL || !pcm_is_ready(pcm)) {
3741 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3742 if (pcm != NULL) {
3743 pcm_close(pcm);
3744 pcm = NULL;
3745 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003746 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003747 return NULL;
3748
Weiyin Jiang72197252019-10-09 11:49:32 +08003749 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003750 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3751 continue;
3752 }
3753 break;
3754 }
3755
3756 if (pcm_is_ready(pcm)) {
3757 int ret = pcm_prepare(pcm);
3758 if (ret < 0) {
3759 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3760 pcm_close(pcm);
3761 pcm = NULL;
3762 }
3763 }
3764
3765 return pcm;
3766}
3767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768int start_output_stream(struct stream_out *out)
3769{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 struct audio_usecase *uc_info;
3772 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003773 char mixer_ctl_name[128];
3774 struct mixer_ctl *ctl = NULL;
3775 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303776 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003777 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778
Haynes Mathew George380745d2017-10-04 15:27:45 -07003779 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003780 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3781 ret = -EINVAL;
3782 goto error_config;
3783 }
3784
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003785 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303786 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003787 get_device_types(&out->device_list), is_haptic_usecase);
3788
3789 bool is_speaker_active = compare_device_type(&out->device_list,
3790 AUDIO_DEVICE_OUT_SPEAKER);
3791 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3792 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303793
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303794 if (CARD_STATUS_OFFLINE == out->card_status ||
3795 CARD_STATUS_OFFLINE == adev->card_status) {
3796 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303797 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003798 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303799 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303800
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003801 //Update incall music usecase to reflect correct voice session
3802 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3803 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3804 if (ret != 0) {
3805 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3806 __func__, ret);
3807 goto error_config;
3808 }
3809 }
3810
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003811 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003812 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003813 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303814 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303815 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303816 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3817 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3818 ret = -EAGAIN;
3819 goto error_config;
3820 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303821 }
3822 }
3823 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003824 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303825 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003826 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303827 //combo usecase just by pass a2dp
3828 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003829 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303830 } else {
3831 ALOGE("%s: SCO profile is not ready, return error", __func__);
3832 ret = -EAGAIN;
3833 goto error_config;
3834 }
3835 }
3836 }
3837
Eric Laurentb23d5282013-05-14 15:27:20 -07003838 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839 if (out->pcm_device_id < 0) {
3840 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3841 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003842 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003843 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844 }
3845
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003846 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003847 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3848 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003849 if (adev->haptic_pcm_device_id < 0) {
3850 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3851 __func__, adev->haptic_pcm_device_id, out->usecase);
3852 ret = -EINVAL;
3853 goto error_config;
3854 }
3855 }
3856
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003858
3859 if (!uc_info) {
3860 ret = -ENOMEM;
3861 goto error_config;
3862 }
3863
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003864 uc_info->id = out->usecase;
3865 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003866 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003867 list_init(&uc_info->device_list);
3868 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003869 uc_info->in_snd_device = SND_DEVICE_NONE;
3870 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003871
3872 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003873 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003874 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3875 /* USB backend is not reopened immediately.
3876 This is eventually done as part of select_devices */
3877 }
3878
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003879 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003880
Wei Wangf7ca6c92017-11-21 14:51:20 -08003881 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303882 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3883 adev->perf_lock_opts,
3884 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303885
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003886 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303887 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303888 if (audio_extn_passthru_is_enabled() &&
3889 audio_extn_passthru_is_passthrough_stream(out)) {
3890 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303891 }
3892 }
3893
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003894 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003895 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303896 if (!a2dp_combo) {
3897 check_a2dp_restore_l(adev, out, false);
3898 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003899 struct listnode dev;
3900 list_init(&dev);
3901 assign_devices(&dev, &out->device_list);
3902 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3903 reassign_device_list(&out->device_list,
3904 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003905 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003906 reassign_device_list(&out->device_list,
3907 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303908 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003909 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303910 }
3911 } else {
3912 select_devices(adev, out->usecase);
3913 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003914
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003915 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3916 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003917 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003918 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003919
Derek Chenea197282019-01-07 17:35:01 -08003920 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3921 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003922
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003923 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3924 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003925
3926 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003927 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003928 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3929 ALOGE("%s: pcm stream not ready", __func__);
3930 goto error_open;
3931 }
3932 ret = pcm_start(out->pcm);
3933 if (ret < 0) {
3934 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3935 goto error_open;
3936 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003937 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003938 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003939 unsigned int flags = PCM_OUT;
3940 unsigned int pcm_open_retry_count = 0;
3941 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3942 flags |= PCM_MMAP | PCM_NOIRQ;
3943 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003944 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003945 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003946 } else
3947 flags |= PCM_MONOTONIC;
3948
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003949 if ((adev->vr_audio_mode_enabled) &&
3950 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3951 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3952 "PCM_Dev %d Topology", out->pcm_device_id);
3953 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3954 if (!ctl) {
3955 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3956 __func__, mixer_ctl_name);
3957 } else {
3958 //if success use ULLPP
3959 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3960 __func__, mixer_ctl_name, out->pcm_device_id);
3961 //There is a still a possibility that some sessions
3962 // that request for FAST|RAW when 3D audio is active
3963 //can go through ULLPP. Ideally we expects apps to
3964 //listen to audio focus and stop concurrent playback
3965 //Also, we will look for mode flag (voice_in_communication)
3966 //before enabling the realtime flag.
3967 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3968 }
3969 }
3970
Surendar Karka91fa3682018-07-02 18:12:12 +05303971 if (out->realtime)
3972 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3973 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3974
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003975 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3976 flags, pcm_open_retry_count,
3977 &(out->config));
3978 if (out->pcm == NULL) {
3979 ret = -EIO;
3980 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003981 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003982
3983 if (is_haptic_usecase) {
3984 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3985 adev->haptic_pcm_device_id,
3986 flags, pcm_open_retry_count,
3987 &(adev->haptics_config));
3988 // failure to open haptics pcm shouldnt stop audio,
3989 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003990
3991 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3992 ALOGD("%s: enable haptic audio synchronization", __func__);
3993 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3994 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003995 }
3996
Surendar Karka91fa3682018-07-02 18:12:12 +05303997 if (!out->realtime)
3998 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303999 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004000
Zhou Song2b8f28f2017-09-11 10:51:38 +08004001 // apply volume for voip playback after path is set up
4002 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4003 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304004 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4005 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304006 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4007 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004008 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4009 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304010 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004011 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004012 /*
4013 * set custom channel map if:
4014 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4015 * 2. custom channel map has been set by client
4016 * else default channel map of FC/FR/FL can always be set to DSP
4017 */
4018 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4019 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4020 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004021 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4022 adev->dsp_bit_width_enforce_mode,
4023 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004025 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004026 out->compr = compress_open(adev->snd_card,
4027 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004028 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004029 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304030 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304031 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4032 adev->card_status = CARD_STATUS_OFFLINE;
4033 out->card_status = CARD_STATUS_OFFLINE;
4034 ret = -EIO;
4035 goto error_open;
4036 }
4037
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004038 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004039 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004040 compress_close(out->compr);
4041 out->compr = NULL;
4042 ret = -EIO;
4043 goto error_open;
4044 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304045 /* compress_open sends params of the track, so reset the flag here */
4046 out->is_compr_metadata_avail = false;
4047
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004048 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004049 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004050
Fred Oh3f43e742015-03-04 18:42:34 -08004051 /* Since small bufs uses blocking writes, a write will be blocked
4052 for the default max poll time (20s) in the event of an SSR.
4053 Reduce the poll time to observe and deal with SSR faster.
4054 */
Ashish Jain5106d362016-05-11 19:23:33 +05304055 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004056 compress_set_max_poll_wait(out->compr, 1000);
4057 }
4058
Manish Dewangan69426c82017-01-30 17:35:36 +05304059 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304060 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304061
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004062 audio_extn_dts_create_state_notifier_node(out->usecase);
4063 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4064 popcount(out->channel_mask),
4065 out->playback_started);
4066
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004067#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304068 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004069 audio_extn_dolby_send_ddp_endp_params(adev);
4070#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304071 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4072 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004073 if (adev->visualizer_start_output != NULL)
4074 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4075 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304076 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004077 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004078 }
Derek Chenf13dd492018-11-13 14:53:51 -08004079
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004080 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004081 /* Update cached volume from media to offload/direct stream */
4082 struct listnode *node = NULL;
4083 list_for_each(node, &adev->active_outputs_list) {
4084 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4085 streams_output_ctxt_t,
4086 list);
4087 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4088 out->volume_l = out_ctxt->output->volume_l;
4089 out->volume_r = out_ctxt->output->volume_r;
4090 }
4091 }
4092 out_set_compr_volume(&out->stream,
4093 out->volume_l, out->volume_r);
4094 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004095 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004096
4097 if (ret == 0) {
4098 register_out_stream(out);
4099 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004100 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4101 ALOGE("%s: pcm stream not ready", __func__);
4102 goto error_open;
4103 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004104 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004105 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004106 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004107 if (ret < 0)
4108 goto error_open;
4109 }
4110 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004111 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304112 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004113 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004114
vivek mehtad15d2bf2019-05-17 13:35:10 -07004115 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4116 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4117 audio_low_latency_hint_start();
4118 }
4119
Manish Dewangan21a850a2017-08-14 12:03:55 +05304120 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004121 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004122 if (ret < 0)
4123 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4124 }
4125
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004126 // consider a scenario where on pause lower layers are tear down.
4127 // so on resume, swap mixer control need to be sent only when
4128 // backend is active, hence rather than sending from enable device
4129 // sending it from start of streamtream
4130
4131 platform_set_swap_channels(adev, true);
4132
Haynes Mathew George380745d2017-10-04 15:27:45 -07004133 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304134 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004135 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004136error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004137 if (adev->haptic_pcm) {
4138 pcm_close(adev->haptic_pcm);
4139 adev->haptic_pcm = NULL;
4140 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004141 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304142 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004144error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304145 /*
4146 * sleep 50ms to allow sufficient time for kernel
4147 * drivers to recover incases like SSR.
4148 */
4149 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004150error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004151 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304152 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004153 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004154}
4155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156static int check_input_parameters(uint32_t sample_rate,
4157 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004158 int channel_count,
4159 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004160{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004161 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304163 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4164 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4165 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004166 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004167 !audio_extn_compr_cap_format_supported(format) &&
4168 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004169 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004170
Aalique Grahame22e49102018-12-18 14:23:57 -08004171 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4172 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4173 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4174 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4175 return -EINVAL;
4176 }
4177
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004178 switch (channel_count) {
4179 case 1:
4180 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304181 case 3:
4182 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004183 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004184 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304185 case 10:
4186 case 12:
4187 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004188 break;
4189 default:
4190 ret = -EINVAL;
4191 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004192
4193 switch (sample_rate) {
4194 case 8000:
4195 case 11025:
4196 case 12000:
4197 case 16000:
4198 case 22050:
4199 case 24000:
4200 case 32000:
4201 case 44100:
4202 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004203 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304204 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004205 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304206 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207 break;
4208 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004209 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210 }
4211
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004212 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004213}
4214
Naresh Tanniru04f71882018-06-26 17:46:22 +05304215
4216/** Add a value in a list if not already present.
4217 * @return true if value was successfully inserted or already present,
4218 * false if the list is full and does not contain the value.
4219 */
4220static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4221 for (size_t i = 0; i < list_length; i++) {
4222 if (list[i] == value) return true; // value is already present
4223 if (list[i] == 0) { // no values in this slot
4224 list[i] = value;
4225 return true; // value inserted
4226 }
4227 }
4228 return false; // could not insert value
4229}
4230
4231/** Add channel_mask in supported_channel_masks if not already present.
4232 * @return true if channel_mask was successfully inserted or already present,
4233 * false if supported_channel_masks is full and does not contain channel_mask.
4234 */
4235static void register_channel_mask(audio_channel_mask_t channel_mask,
4236 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4237 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4238 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4239}
4240
4241/** Add format in supported_formats if not already present.
4242 * @return true if format was successfully inserted or already present,
4243 * false if supported_formats is full and does not contain format.
4244 */
4245static void register_format(audio_format_t format,
4246 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4247 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4248 "%s: stream can not declare supporting its format %x", __func__, format);
4249}
4250/** Add sample_rate in supported_sample_rates if not already present.
4251 * @return true if sample_rate was successfully inserted or already present,
4252 * false if supported_sample_rates is full and does not contain sample_rate.
4253 */
4254static void register_sample_rate(uint32_t sample_rate,
4255 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4256 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4257 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4258}
4259
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004260static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4261{
4262 uint32_t high = num1, low = num2, temp = 0;
4263
4264 if (!num1 || !num2)
4265 return 0;
4266
4267 if (num1 < num2) {
4268 high = num2;
4269 low = num1;
4270 }
4271
4272 while (low != 0) {
4273 temp = low;
4274 low = high % low;
4275 high = temp;
4276 }
4277 return (num1 * num2)/high;
4278}
4279
4280static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4281{
4282 uint32_t remainder = 0;
4283
4284 if (!multiplier)
4285 return num;
4286
4287 remainder = num % multiplier;
4288 if (remainder)
4289 num += (multiplier - remainder);
4290
4291 return num;
4292}
4293
Aalique Grahame22e49102018-12-18 14:23:57 -08004294static size_t get_stream_buffer_size(size_t duration_ms,
4295 uint32_t sample_rate,
4296 audio_format_t format,
4297 int channel_count,
4298 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004299{
4300 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004301 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302
Aalique Grahame22e49102018-12-18 14:23:57 -08004303 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004304 if (is_low_latency)
4305 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304306
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004307 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004308 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309
Ralf Herzbd08d632018-09-28 15:50:49 +02004310 /* make sure the size is multiple of 32 bytes and additionally multiple of
4311 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004312 * At 48 kHz mono 16-bit PCM:
4313 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4314 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004315 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004316 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004317 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004318
4319 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320}
4321
Aalique Grahame22e49102018-12-18 14:23:57 -08004322static size_t get_input_buffer_size(uint32_t sample_rate,
4323 audio_format_t format,
4324 int channel_count,
4325 bool is_low_latency)
4326{
4327 /* Don't know if USB HIFI in this context so use true to be conservative */
4328 if (check_input_parameters(sample_rate, format, channel_count,
4329 true /*is_usb_hifi */) != 0)
4330 return 0;
4331
4332 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4333 sample_rate,
4334 format,
4335 channel_count,
4336 is_low_latency);
4337}
4338
Derek Chenf6318be2017-06-12 17:16:24 -04004339size_t get_output_period_size(uint32_t sample_rate,
4340 audio_format_t format,
4341 int channel_count,
4342 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304343{
4344 size_t size = 0;
4345 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4346
4347 if ((duration == 0) || (sample_rate == 0) ||
4348 (bytes_per_sample == 0) || (channel_count == 0)) {
4349 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4350 bytes_per_sample, channel_count);
4351 return -EINVAL;
4352 }
4353
4354 size = (sample_rate *
4355 duration *
4356 bytes_per_sample *
4357 channel_count) / 1000;
4358 /*
4359 * To have same PCM samples for all channels, the buffer size requires to
4360 * be multiple of (number of channels * bytes per sample)
4361 * For writes to succeed, the buffer must be written at address which is multiple of 32
4362 */
4363 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4364
4365 return (size/(channel_count * bytes_per_sample));
4366}
4367
Zhou Song48453a02018-01-10 17:50:59 +08004368static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304369{
4370 uint64_t actual_frames_rendered = 0;
4371 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4372
4373 /* This adjustment accounts for buffering after app processor.
4374 * It is based on estimated DSP latency per use case, rather than exact.
4375 */
Robert Lee58215542019-07-15 20:55:12 +08004376 pthread_mutex_lock(&adev->lock);
4377 int64_t platform_latency = platform_render_latency(out->dev, out->usecase) *
Ashish Jain5106d362016-05-11 19:23:33 +05304378 out->sample_rate / 1000000LL;
Robert Lee58215542019-07-15 20:55:12 +08004379 pthread_mutex_unlock(&adev->lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304380
Zhou Song48453a02018-01-10 17:50:59 +08004381 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304382 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4383 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4384 * hence only estimate.
4385 */
George Gao62ebc722019-07-29 16:29:44 -07004386 uint64_t signed_frames = 0;
4387 if (out->written >= kernel_buffer_size)
4388 signed_frames = out->written - kernel_buffer_size;
Ashish Jain5106d362016-05-11 19:23:33 +05304389
George Gao62ebc722019-07-29 16:29:44 -07004390 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask));
4391 if (signed_frames >= platform_latency)
4392 signed_frames = signed_frames - platform_latency;
Ashish Jain5106d362016-05-11 19:23:33 +05304393
Zhou Song48453a02018-01-10 17:50:59 +08004394 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304395 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004396 if (timestamp != NULL )
4397 *timestamp = out->writeAt;
4398 } else if (timestamp != NULL) {
4399 clock_gettime(CLOCK_MONOTONIC, timestamp);
4400 }
4401 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304402
4403 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
George Gao62ebc722019-07-29 16:29:44 -07004404 "bytes/sample %zu channel count %d", __func__, signed_frames,
Ashish Jain5106d362016-05-11 19:23:33 +05304405 (long long int)out->written, (int)kernel_buffer_size,
4406 audio_bytes_per_sample(out->compr_config.codec->format),
4407 popcount(out->channel_mask));
4408
4409 return actual_frames_rendered;
4410}
4411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004412static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4413{
4414 struct stream_out *out = (struct stream_out *)stream;
4415
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004416 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004417}
4418
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004419static int out_set_sample_rate(struct audio_stream *stream __unused,
4420 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421{
4422 return -ENOSYS;
4423}
4424
4425static size_t out_get_buffer_size(const struct audio_stream *stream)
4426{
4427 struct stream_out *out = (struct stream_out *)stream;
4428
Varun Balaraje49253e2017-07-06 19:48:56 +05304429 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304430 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304431 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304432 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4433 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4434 else
4435 return out->compr_config.fragment_size;
4436 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004437 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304438 else if (is_offload_usecase(out->usecase) &&
4439 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304440 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004441
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004442 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004443 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444}
4445
4446static uint32_t out_get_channels(const struct audio_stream *stream)
4447{
4448 struct stream_out *out = (struct stream_out *)stream;
4449
4450 return out->channel_mask;
4451}
4452
4453static audio_format_t out_get_format(const struct audio_stream *stream)
4454{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004455 struct stream_out *out = (struct stream_out *)stream;
4456
4457 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004458}
4459
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004460static int out_set_format(struct audio_stream *stream __unused,
4461 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004462{
4463 return -ENOSYS;
4464}
4465
4466static int out_standby(struct audio_stream *stream)
4467{
4468 struct stream_out *out = (struct stream_out *)stream;
4469 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004470 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004471
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304472 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4473 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004474
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004475 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004476 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004477 if (adev->adm_deregister_stream)
4478 adev->adm_deregister_stream(adev->adm_data, out->handle);
4479
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004480 if (is_offload_usecase(out->usecase))
4481 stop_compressed_output_l(out);
4482
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004483 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004484 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004485 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4486 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304487 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004488 pthread_mutex_unlock(&adev->lock);
4489 pthread_mutex_unlock(&out->lock);
4490 ALOGD("VOIP output entered standby");
4491 return 0;
4492 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004493 if (out->pcm) {
4494 pcm_close(out->pcm);
4495 out->pcm = NULL;
4496 }
Meng Wanga09da002020-04-20 12:56:04 +08004497 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4498 if (adev->haptic_pcm) {
4499 pcm_close(adev->haptic_pcm);
4500 adev->haptic_pcm = NULL;
4501 }
4502
4503 if (adev->haptic_buffer != NULL) {
4504 free(adev->haptic_buffer);
4505 adev->haptic_buffer = NULL;
4506 adev->haptic_buffer_size = 0;
4507 }
4508 adev->haptic_pcm_device_id = 0;
4509 }
4510
Haynes Mathew George16081042017-05-31 17:16:49 -07004511 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4512 do_stop = out->playback_started;
4513 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004514
4515 if (out->mmap_shared_memory_fd >= 0) {
4516 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4517 __func__, out->mmap_shared_memory_fd);
4518 close(out->mmap_shared_memory_fd);
4519 out->mmap_shared_memory_fd = -1;
4520 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004521 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004522 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004523 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304524 out->send_next_track_params = false;
4525 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004526 out->gapless_mdata.encoder_delay = 0;
4527 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004528 if (out->compr != NULL) {
4529 compress_close(out->compr);
4530 out->compr = NULL;
4531 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004532 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004533 if (do_stop) {
4534 stop_output_stream(out);
4535 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304536 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004537 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004538 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004539 }
4540 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304541 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004542 return 0;
4543}
4544
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304545static int out_on_error(struct audio_stream *stream)
4546{
4547 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004548 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304549
4550 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004551 // always send CMD_ERROR for offload streams, this
4552 // is needed e.g. when SSR happens within compress_open
4553 // since the stream is active, offload_callback_thread is also active.
4554 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4555 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004556 }
4557 pthread_mutex_unlock(&out->lock);
4558
4559 status = out_standby(&out->stream.common);
4560
4561 lock_output_stream(out);
4562 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004563 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304564 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304565
4566 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4567 ALOGD("Setting previous card status if offline");
4568 out->prev_card_status_offline = true;
4569 }
4570
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304571 pthread_mutex_unlock(&out->lock);
4572
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004573 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304574}
4575
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304576/*
4577 *standby implementation without locks, assumes that the callee already
4578 *has taken adev and out lock.
4579 */
4580int out_standby_l(struct audio_stream *stream)
4581{
4582 struct stream_out *out = (struct stream_out *)stream;
4583 struct audio_device *adev = out->dev;
4584
4585 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4586 stream, out->usecase, use_case_table[out->usecase]);
4587
4588 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004589 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304590 if (adev->adm_deregister_stream)
4591 adev->adm_deregister_stream(adev->adm_data, out->handle);
4592
4593 if (is_offload_usecase(out->usecase))
4594 stop_compressed_output_l(out);
4595
4596 out->standby = true;
4597 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4598 voice_extn_compress_voip_close_output_stream(stream);
4599 out->started = 0;
4600 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004601 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304602 return 0;
4603 } else if (!is_offload_usecase(out->usecase)) {
4604 if (out->pcm) {
4605 pcm_close(out->pcm);
4606 out->pcm = NULL;
4607 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004608 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4609 if (adev->haptic_pcm) {
4610 pcm_close(adev->haptic_pcm);
4611 adev->haptic_pcm = NULL;
4612 }
4613
4614 if (adev->haptic_buffer != NULL) {
4615 free(adev->haptic_buffer);
4616 adev->haptic_buffer = NULL;
4617 adev->haptic_buffer_size = 0;
4618 }
4619 adev->haptic_pcm_device_id = 0;
4620 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304621 } else {
4622 ALOGD("copl(%p):standby", out);
4623 out->send_next_track_params = false;
4624 out->is_compr_metadata_avail = false;
4625 out->gapless_mdata.encoder_delay = 0;
4626 out->gapless_mdata.encoder_padding = 0;
4627 if (out->compr != NULL) {
4628 compress_close(out->compr);
4629 out->compr = NULL;
4630 }
4631 }
4632 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004633 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304634 }
4635 ALOGD("%s: exit", __func__);
4636 return 0;
4637}
4638
Aalique Grahame22e49102018-12-18 14:23:57 -08004639static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640{
Aalique Grahame22e49102018-12-18 14:23:57 -08004641 struct stream_out *out = (struct stream_out *)stream;
4642
4643 // We try to get the lock for consistency,
4644 // but it isn't necessary for these variables.
4645 // If we're not in standby, we may be blocked on a write.
4646 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4647 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4648 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4649
Andy Hunga1f48fa2019-07-01 18:14:53 -07004650 char buffer[256]; // for statistics formatting
4651 if (!is_offload_usecase(out->usecase)) {
4652 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4653 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4654 }
4655
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004656 if (out->start_latency_ms.n > 0) {
4657 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4658 dprintf(fd, " Start latency ms: %s\n", buffer);
4659 }
4660
Aalique Grahame22e49102018-12-18 14:23:57 -08004661 if (locked) {
4662 pthread_mutex_unlock(&out->lock);
4663 }
4664
4665 // dump error info
4666 (void)error_log_dump(
4667 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004669 return 0;
4670}
4671
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004672static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4673{
4674 int ret = 0;
4675 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004676
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004677 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004678 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004679 return -EINVAL;
4680 }
4681
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304682 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004683
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004684 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4685 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304686 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004687 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004688 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4689 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304690 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004691 }
4692
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004693 ALOGV("%s new encoder delay %u and padding %u", __func__,
4694 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4695
4696 return 0;
4697}
4698
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004699static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4700{
4701 return out == adev->primary_output || out == adev->voice_tx_output;
4702}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004703
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304704// note: this call is safe only if the stream_cb is
4705// removed first in close_output_stream (as is done now).
4706static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4707{
4708 if (!stream || !parms)
4709 return;
4710
4711 struct stream_out *out = (struct stream_out *)stream;
4712 struct audio_device *adev = out->dev;
4713
4714 card_status_t status;
4715 int card;
4716 if (parse_snd_card_status(parms, &card, &status) < 0)
4717 return;
4718
4719 pthread_mutex_lock(&adev->lock);
4720 bool valid_cb = (card == adev->snd_card);
4721 pthread_mutex_unlock(&adev->lock);
4722
4723 if (!valid_cb)
4724 return;
4725
4726 lock_output_stream(out);
4727 if (out->card_status != status)
4728 out->card_status = status;
4729 pthread_mutex_unlock(&out->lock);
4730
4731 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4732 use_case_table[out->usecase],
4733 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4734
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304735 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304736 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304737 if (voice_is_call_state_active(adev) &&
4738 out == adev->primary_output) {
4739 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4740 pthread_mutex_lock(&adev->lock);
4741 voice_stop_call(adev);
4742 adev->mode = AUDIO_MODE_NORMAL;
4743 pthread_mutex_unlock(&adev->lock);
4744 }
4745 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304746 return;
4747}
4748
Kevin Rocardfce19002017-08-07 19:21:36 -07004749static int get_alive_usb_card(struct str_parms* parms) {
4750 int card;
4751 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4752 !audio_extn_usb_alive(card)) {
4753 return card;
4754 }
4755 return -ENODEV;
4756}
4757
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004758int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004759 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004760{
4761 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004762 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004763 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004764 bool bypass_a2dp = false;
4765 bool reconfig = false;
4766 unsigned long service_interval = 0;
4767
4768 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004769 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4770
4771 list_init(&new_devices);
4772 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004773
4774 lock_output_stream(out);
4775 pthread_mutex_lock(&adev->lock);
4776
4777 /*
4778 * When HDMI cable is unplugged the music playback is paused and
4779 * the policy manager sends routing=0. But the audioflinger continues
4780 * to write data until standby time (3sec). As the HDMI core is
4781 * turned off, the write gets blocked.
4782 * Avoid this by routing audio to speaker until standby.
4783 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004784 if (is_single_device_type_equal(&out->device_list,
4785 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004786 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004787 !audio_extn_passthru_is_passthrough_stream(out) &&
4788 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004789 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004790 }
4791 /*
4792 * When A2DP is disconnected the
4793 * music playback is paused and the policy manager sends routing=0
4794 * But the audioflinger continues to write data until standby time
4795 * (3sec). As BT is turned off, the write gets blocked.
4796 * Avoid this by routing audio to speaker until standby.
4797 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004798 if (is_a2dp_out_device_type(&out->device_list) &&
4799 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004800 !audio_extn_a2dp_source_is_ready() &&
4801 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004802 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004803 }
4804 /*
4805 * When USB headset is disconnected the music platback paused
4806 * and the policy manager send routing=0. But if the USB is connected
4807 * back before the standby time, AFE is not closed and opened
4808 * when USB is connected back. So routing to speker will guarantee
4809 * AFE reconfiguration and AFE will be opend once USB is connected again
4810 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004811 if (is_usb_out_device_type(&out->device_list) &&
4812 list_empty(&new_devices) &&
4813 !audio_extn_usb_connected(NULL)) {
4814 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4815 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004816 /* To avoid a2dp to sco overlapping / BT device improper state
4817 * check with BT lib about a2dp streaming support before routing
4818 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004819 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004820 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004821 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4822 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004823 //combo usecase just by pass a2dp
4824 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4825 bypass_a2dp = true;
4826 } else {
4827 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4828 /* update device to a2dp and don't route as BT returned error
4829 * However it is still possible a2dp routing called because
4830 * of current active device disconnection (like wired headset)
4831 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004832 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004833 pthread_mutex_unlock(&adev->lock);
4834 pthread_mutex_unlock(&out->lock);
4835 goto error;
4836 }
4837 }
4838 }
4839
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004840 // Workaround: If routing to an non existing usb device, fail gracefully
4841 // The routing request will otherwise block during 10 second
4842 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004843 if (is_usb_out_device_type(&new_devices)) {
4844 struct str_parms *parms =
4845 str_parms_create_str(get_usb_device_address(&new_devices));
4846 if (!parms)
4847 goto error;
4848 if ((card = get_alive_usb_card(parms)) >= 0) {
4849 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4850 pthread_mutex_unlock(&adev->lock);
4851 pthread_mutex_unlock(&out->lock);
4852 str_parms_destroy(parms);
4853 ret = -ENOSYS;
4854 goto error;
4855 }
4856 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004857 }
4858
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004859 // Workaround: If routing to an non existing hdmi device, fail gracefully
4860 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4861 (platform_get_edid_info_v2(adev->platform,
4862 out->extconn.cs.controller,
4863 out->extconn.cs.stream) != 0)) {
4864 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4865 pthread_mutex_unlock(&adev->lock);
4866 pthread_mutex_unlock(&out->lock);
4867 ret = -ENOSYS;
4868 goto error;
4869 }
4870
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004871 /*
4872 * select_devices() call below switches all the usecases on the same
4873 * backend to the new device. Refer to check_usecases_codec_backend() in
4874 * the select_devices(). But how do we undo this?
4875 *
4876 * For example, music playback is active on headset (deep-buffer usecase)
4877 * and if we go to ringtones and select a ringtone, low-latency usecase
4878 * will be started on headset+speaker. As we can't enable headset+speaker
4879 * and headset devices at the same time, select_devices() switches the music
4880 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4881 * So when the ringtone playback is completed, how do we undo the same?
4882 *
4883 * We are relying on the out_set_parameters() call on deep-buffer output,
4884 * once the ringtone playback is ended.
4885 * NOTE: We should not check if the current devices are same as new devices.
4886 * Because select_devices() must be called to switch back the music
4887 * playback to headset.
4888 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004889 if (!list_empty(&new_devices)) {
4890 bool same_dev = compare_devices(&out->device_list, &new_devices);
4891 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004892
4893 if (output_drives_call(adev, out)) {
4894 if (!voice_is_call_state_active(adev)) {
4895 if (adev->mode == AUDIO_MODE_IN_CALL) {
4896 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004897 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004898 service_interval =
4899 audio_extn_usb_find_service_interval(true, true /*playback*/);
4900 audio_extn_usb_set_service_interval(true /*playback*/,
4901 service_interval,
4902 &reconfig);
4903 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4904 }
4905 ret = voice_start_call(adev);
4906 }
4907 } else {
4908 adev->current_call_output = out;
4909 voice_update_devices_for_all_voice_usecases(adev);
4910 }
4911 }
4912
4913 if (!out->standby) {
4914 if (!same_dev) {
4915 ALOGV("update routing change");
4916 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4917 adev->perf_lock_opts,
4918 adev->perf_lock_opts_size);
4919 if (adev->adm_on_routing_change)
4920 adev->adm_on_routing_change(adev->adm_data,
4921 out->handle);
4922 }
4923 if (!bypass_a2dp) {
4924 select_devices(adev, out->usecase);
4925 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004926 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4927 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004928 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004929 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004930 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004931 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004932 }
4933
4934 if (!same_dev) {
4935 // on device switch force swap, lower functions will make sure
4936 // to check if swap is allowed or not.
4937 platform_set_swap_channels(adev, true);
4938 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4939 }
4940 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4941 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004942 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004943 pthread_mutex_lock(&out->compr_mute_lock);
4944 out->a2dp_compress_mute = false;
4945 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4946 pthread_mutex_unlock(&out->compr_mute_lock);
4947 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4948 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4949 }
4950 }
4951 }
4952
4953 pthread_mutex_unlock(&adev->lock);
4954 pthread_mutex_unlock(&out->lock);
4955
4956 /*handles device and call state changes*/
4957 audio_extn_extspk_update(adev->extspk);
4958
4959error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004960 ALOGV("%s: exit: code(%d)", __func__, ret);
4961 return ret;
4962}
4963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004964static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4965{
4966 struct stream_out *out = (struct stream_out *)stream;
4967 struct audio_device *adev = out->dev;
4968 struct str_parms *parms;
4969 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004970 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004971 int ext_controller = -1;
4972 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004973
sangwoobc677242013-08-08 16:53:43 +09004974 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004975 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004976 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304977 if (!parms)
4978 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004979
4980 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4981 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08004982 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004983 out->extconn.cs.controller = ext_controller;
4984 out->extconn.cs.stream = ext_stream;
4985 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4986 use_case_table[out->usecase], out->extconn.cs.controller,
4987 out->extconn.cs.stream);
4988 }
4989
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004990 if (out == adev->primary_output) {
4991 pthread_mutex_lock(&adev->lock);
4992 audio_extn_set_parameters(adev, parms);
4993 pthread_mutex_unlock(&adev->lock);
4994 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004995 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004996 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004997 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004998
4999 audio_extn_dts_create_state_notifier_node(out->usecase);
5000 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5001 popcount(out->channel_mask),
5002 out->playback_started);
5003
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005004 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005005 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005006
Surendar Karkaf51b5842018-04-26 11:28:38 +05305007 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5008 sizeof(value));
5009 if (err >= 0) {
5010 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5011 audio_extn_send_dual_mono_mixing_coefficients(out);
5012 }
5013
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305014 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5015 if (err >= 0) {
5016 strlcpy(out->profile, value, sizeof(out->profile));
5017 ALOGV("updating stream profile with value '%s'", out->profile);
5018 lock_output_stream(out);
5019 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5020 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005021 &out->device_list, out->flags,
5022 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305023 out->sample_rate, out->bit_width,
5024 out->channel_mask, out->profile,
5025 &out->app_type_cfg);
5026 pthread_mutex_unlock(&out->lock);
5027 }
5028
Alexy Joseph98988832017-01-13 14:56:59 -08005029 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005030 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5031 // and vendor.audio.hal.output.suspend.supported is set to true
5032 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005033 //check suspend parameter only for low latency and if the property
5034 //is enabled
5035 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5036 ALOGI("%s: got suspend_playback %s", __func__, value);
5037 lock_output_stream(out);
5038 if (!strncmp(value, "false", 5)) {
5039 //suspend_playback=false is supposed to set QOS value back to 75%
5040 //the mixer control sent with value Enable will achieve that
5041 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5042 } else if (!strncmp (value, "true", 4)) {
5043 //suspend_playback=true is supposed to remove QOS value
5044 //resetting the mixer control will set the default value
5045 //for the mixer control which is Disable and this removes the QOS vote
5046 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5047 } else {
5048 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5049 " got %s", __func__, value);
5050 ret = -1;
5051 }
5052
5053 if (ret != 0) {
5054 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5055 __func__, out->pm_qos_mixer_path, ret);
5056 }
5057
5058 pthread_mutex_unlock(&out->lock);
5059 }
5060 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005061
Alexy Joseph98988832017-01-13 14:56:59 -08005062 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005063 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305064error:
Eric Laurent994a6932013-07-17 11:51:42 -07005065 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005066 return ret;
5067}
5068
Paul McLeana50b7332018-12-17 08:24:21 -07005069static int in_set_microphone_direction(const struct audio_stream_in *stream,
5070 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005071 struct stream_in *in = (struct stream_in *)stream;
5072
5073 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5074
5075 in->direction = dir;
5076
5077 if (in->standby)
5078 return 0;
5079
5080 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005081}
5082
5083static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005084 struct stream_in *in = (struct stream_in *)stream;
5085
5086 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5087
5088 if (zoom > 1.0 || zoom < -1.0)
5089 return -EINVAL;
5090
5091 in->zoom = zoom;
5092
5093 if (in->standby)
5094 return 0;
5095
5096 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005097}
5098
5099
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005100static bool stream_get_parameter_channels(struct str_parms *query,
5101 struct str_parms *reply,
5102 audio_channel_mask_t *supported_channel_masks) {
5103 int ret = -1;
5104 char value[512];
5105 bool first = true;
5106 size_t i, j;
5107
5108 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5109 ret = 0;
5110 value[0] = '\0';
5111 i = 0;
5112 while (supported_channel_masks[i] != 0) {
5113 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5114 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5115 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305116 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005117
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305118 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005119 first = false;
5120 break;
5121 }
5122 }
5123 i++;
5124 }
5125 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5126 }
5127 return ret == 0;
5128}
5129
5130static bool stream_get_parameter_formats(struct str_parms *query,
5131 struct str_parms *reply,
5132 audio_format_t *supported_formats) {
5133 int ret = -1;
5134 char value[256];
5135 size_t i, j;
5136 bool first = true;
5137
5138 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5139 ret = 0;
5140 value[0] = '\0';
5141 i = 0;
5142 while (supported_formats[i] != 0) {
5143 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5144 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5145 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305146 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005147 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305148 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005149 first = false;
5150 break;
5151 }
5152 }
5153 i++;
5154 }
5155 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5156 }
5157 return ret == 0;
5158}
5159
5160static bool stream_get_parameter_rates(struct str_parms *query,
5161 struct str_parms *reply,
5162 uint32_t *supported_sample_rates) {
5163
5164 int i;
5165 char value[256];
5166 int ret = -1;
5167 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5168 ret = 0;
5169 value[0] = '\0';
5170 i=0;
5171 int cursor = 0;
5172 while (supported_sample_rates[i]) {
5173 int avail = sizeof(value) - cursor;
5174 ret = snprintf(value + cursor, avail, "%s%d",
5175 cursor > 0 ? "|" : "",
5176 supported_sample_rates[i]);
5177 if (ret < 0 || ret >= avail) {
5178 // if cursor is at the last element of the array
5179 // overwrite with \0 is duplicate work as
5180 // snprintf already put a \0 in place.
5181 // else
5182 // we had space to write the '|' at value[cursor]
5183 // (which will be overwritten) or no space to fill
5184 // the first element (=> cursor == 0)
5185 value[cursor] = '\0';
5186 break;
5187 }
5188 cursor += ret;
5189 ++i;
5190 }
5191 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5192 value);
5193 }
5194 return ret >= 0;
5195}
5196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005197static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5198{
5199 struct stream_out *out = (struct stream_out *)stream;
5200 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005201 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005202 char value[256];
5203 struct str_parms *reply = str_parms_create();
5204 size_t i, j;
5205 int ret;
5206 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005207
5208 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005209 if (reply) {
5210 str_parms_destroy(reply);
5211 }
5212 if (query) {
5213 str_parms_destroy(query);
5214 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005215 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5216 return NULL;
5217 }
5218
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005219 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005220 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5221 if (ret >= 0) {
5222 value[0] = '\0';
5223 i = 0;
5224 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005225 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5226 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005227 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005228 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005229 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005230 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005231 first = false;
5232 break;
5233 }
5234 }
5235 i++;
5236 }
5237 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5238 str = str_parms_to_str(reply);
5239 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005240 voice_extn_out_get_parameters(out, query, reply);
5241 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005242 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005243
Alexy Joseph62142aa2015-11-16 15:10:34 -08005244
5245 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5246 if (ret >= 0) {
5247 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305248 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5249 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005250 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305251 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005252 } else {
5253 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305254 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005255 }
5256 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005257 if (str)
5258 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005259 str = str_parms_to_str(reply);
5260 }
5261
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005262 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5263 if (ret >= 0) {
5264 value[0] = '\0';
5265 i = 0;
5266 first = true;
5267 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005268 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5269 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005270 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005271 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005272 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005273 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005274 first = false;
5275 break;
5276 }
5277 }
5278 i++;
5279 }
5280 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005281 if (str)
5282 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005283 str = str_parms_to_str(reply);
5284 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005285
5286 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5287 if (ret >= 0) {
5288 value[0] = '\0';
5289 i = 0;
5290 first = true;
5291 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005292 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5293 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005294 if (!first) {
5295 strlcat(value, "|", sizeof(value));
5296 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005297 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005298 first = false;
5299 break;
5300 }
5301 }
5302 i++;
5303 }
5304 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5305 if (str)
5306 free(str);
5307 str = str_parms_to_str(reply);
5308 }
5309
Alexy Joseph98988832017-01-13 14:56:59 -08005310 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5311 //only low latency track supports suspend_resume
5312 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005313 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005314 if (str)
5315 free(str);
5316 str = str_parms_to_str(reply);
5317 }
5318
5319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005320 str_parms_destroy(query);
5321 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005322 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005323 return str;
5324}
5325
5326static uint32_t out_get_latency(const struct audio_stream_out *stream)
5327{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005328 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005329 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005330 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005331
Alexy Josephaa54c872014-12-03 02:46:47 -08005332 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305333 lock_output_stream(out);
5334 latency = audio_extn_utils_compress_get_dsp_latency(out);
5335 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005336 } else if ((out->realtime) ||
5337 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005338 // since the buffer won't be filled up faster than realtime,
5339 // return a smaller number
5340 if (out->config.rate)
5341 period_ms = (out->af_period_multiplier * out->config.period_size *
5342 1000) / (out->config.rate);
5343 else
5344 period_ms = 0;
Robert Lee58215542019-07-15 20:55:12 +08005345 pthread_mutex_lock(&adev->lock);
5346 latency = period_ms + platform_render_latency(out->dev, out->usecase)/1000;
5347 pthread_mutex_unlock(&adev->lock);
Alexy Josephaa54c872014-12-03 02:46:47 -08005348 } else {
5349 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005350 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005351 }
5352
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005353 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005354 latency += audio_extn_a2dp_get_encoder_latency();
5355
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305356 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005357 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005358}
5359
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305360static float AmpToDb(float amplification)
5361{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305362 float db = DSD_VOLUME_MIN_DB;
5363 if (amplification > 0) {
5364 db = 20 * log10(amplification);
5365 if(db < DSD_VOLUME_MIN_DB)
5366 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305367 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305368 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305369}
5370
Arun Mirpuri5d170872019-03-26 13:21:31 -07005371static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5372 float right)
5373{
5374 struct stream_out *out = (struct stream_out *)stream;
5375 long volume = 0;
5376 char mixer_ctl_name[128] = "";
5377 struct audio_device *adev = out->dev;
5378 struct mixer_ctl *ctl = NULL;
5379 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5380 PCM_PLAYBACK);
5381
5382 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5383 "Playback %d Volume", pcm_device_id);
5384 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5385 if (!ctl) {
5386 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5387 __func__, mixer_ctl_name);
5388 return -EINVAL;
5389 }
5390 if (left != right)
5391 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5392 __func__, left, right);
5393 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5394 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5395 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5396 __func__, mixer_ctl_name, volume);
5397 return -EINVAL;
5398 }
5399 return 0;
5400}
5401
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305402static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5403 float right)
5404{
5405 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305406 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305407 char mixer_ctl_name[128];
5408 struct audio_device *adev = out->dev;
5409 struct mixer_ctl *ctl;
5410 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5411 PCM_PLAYBACK);
5412
5413 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5414 "Compress Playback %d Volume", pcm_device_id);
5415 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5416 if (!ctl) {
5417 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5418 __func__, mixer_ctl_name);
5419 return -EINVAL;
5420 }
5421 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5422 __func__, mixer_ctl_name, left, right);
5423 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5424 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5425 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5426
5427 return 0;
5428}
5429
Zhou Song2b8f28f2017-09-11 10:51:38 +08005430static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5431 float right)
5432{
5433 struct stream_out *out = (struct stream_out *)stream;
5434 char mixer_ctl_name[] = "App Type Gain";
5435 struct audio_device *adev = out->dev;
5436 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305437 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005438
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005439 if (!is_valid_volume(left, right)) {
5440 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5441 __func__, left, right);
5442 return -EINVAL;
5443 }
5444
Zhou Song2b8f28f2017-09-11 10:51:38 +08005445 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5446 if (!ctl) {
5447 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5448 __func__, mixer_ctl_name);
5449 return -EINVAL;
5450 }
5451
5452 set_values[0] = 0; //0: Rx Session 1:Tx Session
5453 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305454 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5455 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005456
5457 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5458 return 0;
5459}
5460
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305461static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5462 float right)
5463{
5464 struct stream_out *out = (struct stream_out *)stream;
5465 /* Volume control for pcm playback */
5466 if (left != right) {
5467 return -EINVAL;
5468 } else {
5469 char mixer_ctl_name[128];
5470 struct audio_device *adev = out->dev;
5471 struct mixer_ctl *ctl;
5472 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5473 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5474 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5475 if (!ctl) {
5476 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5477 return -EINVAL;
5478 }
5479
5480 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5481 int ret = mixer_ctl_set_value(ctl, 0, volume);
5482 if (ret < 0) {
5483 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5484 return -EINVAL;
5485 }
5486
5487 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5488
5489 return 0;
5490 }
5491}
5492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005493static int out_set_volume(struct audio_stream_out *stream, float left,
5494 float right)
5495{
Eric Laurenta9024de2013-04-04 09:19:12 -07005496 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005497 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305498 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005499
Arun Mirpuri5d170872019-03-26 13:21:31 -07005500 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005501 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5502 /* only take left channel into account: the API is for stereo anyway */
5503 out->muted = (left == 0.0f);
5504 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005505 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305506 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005507 /*
5508 * Set mute or umute on HDMI passthrough stream.
5509 * Only take left channel into account.
5510 * Mute is 0 and unmute 1
5511 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305512 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305513 } else if (out->format == AUDIO_FORMAT_DSD){
5514 char mixer_ctl_name[128] = "DSD Volume";
5515 struct audio_device *adev = out->dev;
5516 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5517
5518 if (!ctl) {
5519 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5520 __func__, mixer_ctl_name);
5521 return -EINVAL;
5522 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305523 volume[0] = (long)(AmpToDb(left));
5524 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305525 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5526 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005527 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005528 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005529 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5530 struct listnode *node = NULL;
5531 list_for_each(node, &adev->active_outputs_list) {
5532 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5533 streams_output_ctxt_t,
5534 list);
5535 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5536 out->volume_l = out_ctxt->output->volume_l;
5537 out->volume_r = out_ctxt->output->volume_r;
5538 }
5539 }
5540 if (!out->a2dp_compress_mute) {
5541 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5542 }
5543 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005544 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305545 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005546 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305547 if (!out->a2dp_compress_mute)
5548 ret = out_set_compr_volume(stream, left, right);
5549 out->volume_l = left;
5550 out->volume_r = right;
5551 pthread_mutex_unlock(&out->compr_mute_lock);
5552 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005553 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005554 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005555 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5556 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5557 if (!out->standby) {
5558 audio_extn_utils_send_app_type_gain(out->dev,
5559 out->app_type_cfg.app_type,
5560 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005561 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005562 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005563 out->volume_l = left;
5564 out->volume_r = right;
5565 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005566 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5567 ALOGV("%s: MMAP set volume called", __func__);
5568 if (!out->standby)
5569 ret = out_set_mmap_volume(stream, left, right);
5570 out->volume_l = left;
5571 out->volume_r = right;
5572 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305573 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305574 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5575 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305576 /* Volume control for pcm playback */
5577 if (!out->standby)
5578 ret = out_set_pcm_volume(stream, left, right);
5579 else
5580 out->apply_volume = true;
5581
5582 out->volume_l = left;
5583 out->volume_r = right;
5584 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005585 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5586 ALOGV("%s: bus device set volume called", __func__);
5587 if (!out->standby)
5588 ret = out_set_pcm_volume(stream, left, right);
5589 out->volume_l = left;
5590 out->volume_r = right;
5591 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005592 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005594 return -ENOSYS;
5595}
5596
Zhou Songc9672822017-08-16 16:01:39 +08005597static void update_frames_written(struct stream_out *out, size_t bytes)
5598{
5599 size_t bpf = 0;
5600
5601 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5602 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5603 bpf = 1;
5604 else if (!is_offload_usecase(out->usecase))
5605 bpf = audio_bytes_per_sample(out->format) *
5606 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005607
5608 pthread_mutex_lock(&out->position_query_lock);
5609 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005610 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005611 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5612 }
5613 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005614}
5615
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005616int split_and_write_audio_haptic_data(struct stream_out *out,
5617 const void *buffer, size_t bytes_to_write)
5618{
5619 struct audio_device *adev = out->dev;
5620
5621 int ret = 0;
5622 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5623 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5624 size_t frame_size = channel_count * bytes_per_sample;
5625 size_t frame_count = bytes_to_write / frame_size;
5626
5627 bool force_haptic_path =
5628 property_get_bool("vendor.audio.test_haptic", false);
5629
5630 // extract Haptics data from Audio buffer
5631 bool alloc_haptic_buffer = false;
5632 int haptic_channel_count = adev->haptics_config.channels;
5633 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5634 size_t audio_frame_size = frame_size - haptic_frame_size;
5635 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5636
5637 if (adev->haptic_buffer == NULL) {
5638 alloc_haptic_buffer = true;
5639 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5640 free(adev->haptic_buffer);
5641 adev->haptic_buffer_size = 0;
5642 alloc_haptic_buffer = true;
5643 }
5644
5645 if (alloc_haptic_buffer) {
5646 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005647 if(adev->haptic_buffer == NULL) {
5648 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5649 return -ENOMEM;
5650 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005651 adev->haptic_buffer_size = total_haptic_buffer_size;
5652 }
5653
5654 size_t src_index = 0, aud_index = 0, hap_index = 0;
5655 uint8_t *audio_buffer = (uint8_t *)buffer;
5656 uint8_t *haptic_buffer = adev->haptic_buffer;
5657
5658 // This is required for testing only. This works for stereo data only.
5659 // One channel is fed to audio stream and other to haptic stream for testing.
5660 if (force_haptic_path)
5661 audio_frame_size = haptic_frame_size = bytes_per_sample;
5662
5663 for (size_t i = 0; i < frame_count; i++) {
5664 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5665 audio_frame_size);
5666 aud_index += audio_frame_size;
5667 src_index += audio_frame_size;
5668
5669 if (adev->haptic_pcm)
5670 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5671 haptic_frame_size);
5672 hap_index += haptic_frame_size;
5673 src_index += haptic_frame_size;
5674
5675 // This is required for testing only.
5676 // Discard haptic channel data.
5677 if (force_haptic_path)
5678 src_index += haptic_frame_size;
5679 }
5680
5681 // write to audio pipeline
5682 ret = pcm_write(out->pcm, (void *)audio_buffer,
5683 frame_count * audio_frame_size);
5684
5685 // write to haptics pipeline
5686 if (adev->haptic_pcm)
5687 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5688 frame_count * haptic_frame_size);
5689
5690 return ret;
5691}
5692
Aalique Grahame22e49102018-12-18 14:23:57 -08005693#ifdef NO_AUDIO_OUT
5694static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5695 const void *buffer __unused, size_t bytes)
5696{
5697 struct stream_out *out = (struct stream_out *)stream;
5698
5699 /* No Output device supported other than BT for playback.
5700 * Sleep for the amount of buffer duration
5701 */
5702 lock_output_stream(out);
5703 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5704 (const struct audio_stream_out *)&out->stream) /
5705 out_get_sample_rate(&out->stream.common));
5706 pthread_mutex_unlock(&out->lock);
5707 return bytes;
5708}
5709#endif
5710
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005711static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5712 size_t bytes)
5713{
5714 struct stream_out *out = (struct stream_out *)stream;
5715 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005716 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305717 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005718 const size_t frame_size = audio_stream_out_frame_size(stream);
5719 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305720 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005721 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005722
Haynes Mathew George380745d2017-10-04 15:27:45 -07005723 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005724 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305725
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305726 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005727
Dhananjay Kumarac341582017-02-23 23:42:25 +05305728 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305729 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305730 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5731 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005732 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305733 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305734 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305735 ALOGD(" %s: sound card is not active/SSR state", __func__);
5736 ret= -EIO;
5737 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305738 }
5739 }
5740
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305741 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305742 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305743 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305744 goto exit;
5745 }
5746
Haynes Mathew George16081042017-05-31 17:16:49 -07005747 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5748 ret = -EINVAL;
5749 goto exit;
5750 }
5751
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005752 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305753 !out->is_iec61937_info_available) {
5754
5755 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5756 out->is_iec61937_info_available = true;
5757 } else if (audio_extn_passthru_is_enabled()) {
5758 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305759 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305760
5761 if((out->format == AUDIO_FORMAT_DTS) ||
5762 (out->format == AUDIO_FORMAT_DTS_HD)) {
5763 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5764 buffer, bytes);
5765 if (ret) {
5766 if (ret != -ENOSYS) {
5767 out->is_iec61937_info_available = false;
5768 ALOGD("iec61937 transmission info not yet updated retry");
5769 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305770 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305771 /* if stream has started and after that there is
5772 * stream config change (iec transmission config)
5773 * then trigger select_device to update backend configuration.
5774 */
5775 out->stream_config_changed = true;
5776 pthread_mutex_lock(&adev->lock);
5777 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305778 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005779 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305780 ret = -EINVAL;
5781 goto exit;
5782 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305783 pthread_mutex_unlock(&adev->lock);
5784 out->stream_config_changed = false;
5785 out->is_iec61937_info_available = true;
5786 }
5787 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305788
Meng Wang4c32fb42020-01-16 17:57:11 +08005789#ifdef AUDIO_GKI_ENABLED
5790 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5791 compr_passthr = out->compr_config.codec->reserved[0];
5792#else
5793 compr_passthr = out->compr_config.codec->compr_passthr;
5794#endif
5795
Garmond Leung317cbf12017-09-13 16:20:50 -07005796 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005797 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305798 (out->is_iec61937_info_available == true)) {
5799 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5800 ret = -EINVAL;
5801 goto exit;
5802 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305803 }
5804 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305805
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005806 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005807 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005808 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5809 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305810 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305811 ret = -EIO;
5812 goto exit;
5813 }
5814 }
5815 }
5816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005817 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005818 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005819 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5820
Eric Laurent150dbfe2013-02-27 14:31:02 -08005821 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005822 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5823 ret = voice_extn_compress_voip_start_output_stream(out);
5824 else
5825 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005826 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005827 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005828 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005829 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005830 goto exit;
5831 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305832 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005833 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
vivek mehtab72d08d2016-04-29 03:16:47 -07005834 if (last_known_cal_step != -1) {
5835 ALOGD("%s: retry previous failed cal level set", __func__);
5836 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305837 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005838 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305839
5840 if ((out->is_iec61937_info_available == true) &&
5841 (audio_extn_passthru_is_passthrough_stream(out))&&
5842 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5843 ret = -EINVAL;
5844 goto exit;
5845 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305846 if (out->set_dual_mono)
5847 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005848
5849 // log startup time in ms.
5850 simple_stats_log(
5851 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005852 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005853
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005854 if (adev->is_channel_status_set == false &&
5855 compare_device_type(&out->device_list,
5856 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005857 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305858 adev->is_channel_status_set = true;
5859 }
5860
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305861 if ((adev->use_old_pspd_mix_ctrl == true) &&
5862 (out->pspd_coeff_sent == false)) {
5863 /*
5864 * Need to resend pspd coefficients after stream started for
5865 * older kernel version as it does not save the coefficients
5866 * and also stream has to be started for coeff to apply.
5867 */
5868 usecase = get_usecase_from_list(adev, out->usecase);
5869 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305870 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305871 out->pspd_coeff_sent = true;
5872 }
5873 }
5874
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005875 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005876 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005877 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005878 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005879 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5880 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305881 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5882 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005883 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305884 out->send_next_track_params = false;
5885 out->is_compr_metadata_avail = false;
5886 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005887 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305888 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305889 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005890
Ashish Jain83a6cc22016-06-28 14:34:17 +05305891 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305892 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305893 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305894 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005895 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305896 return -EINVAL;
5897 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305898 audio_format_t dst_format = out->hal_op_format;
5899 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305900
Dieter Luecking5d57def2018-09-07 14:23:37 +02005901 /* prevent division-by-zero */
5902 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5903 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5904 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5905 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305906 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005907 ATRACE_END();
5908 return -EINVAL;
5909 }
5910
Ashish Jainf1eaa582016-05-23 20:54:24 +05305911 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5912 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5913
Ashish Jain83a6cc22016-06-28 14:34:17 +05305914 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305915 dst_format,
5916 buffer,
5917 src_format,
5918 frames);
5919
Ashish Jain83a6cc22016-06-28 14:34:17 +05305920 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305921 bytes_to_write);
5922
5923 /*Convert written bytes in audio flinger format*/
5924 if (ret > 0)
5925 ret = ((ret * format_to_bitwidth_table[out->format]) /
5926 format_to_bitwidth_table[dst_format]);
5927 }
5928 } else
5929 ret = compress_write(out->compr, buffer, bytes);
5930
Zhou Songc9672822017-08-16 16:01:39 +08005931 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5932 update_frames_written(out, bytes);
5933
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305934 if (ret < 0)
5935 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005936 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305937 /*msg to cb thread only if non blocking write is enabled*/
5938 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305939 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005940 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305941 } else if (-ENETRESET == ret) {
5942 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305943 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305944 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305945 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005946 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305947 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005948 }
Ashish Jain5106d362016-05-11 19:23:33 +05305949
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305950 /* Call compr start only when non-zero bytes of data is there to be rendered */
5951 if (!out->playback_started && ret > 0) {
5952 int status = compress_start(out->compr);
5953 if (status < 0) {
5954 ret = status;
5955 ALOGE("%s: compr start failed with err %d", __func__, errno);
5956 goto exit;
5957 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005958 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005959 out->playback_started = 1;
5960 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005961
5962 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5963 popcount(out->channel_mask),
5964 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005965 }
5966 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005967 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005968 return ret;
5969 } else {
5970 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005971 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005972 if (out->muted)
5973 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005974 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5975 __func__, frames, frame_size, bytes_to_write);
5976
Aalique Grahame22e49102018-12-18 14:23:57 -08005977 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005978 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5979 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5980 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005981 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5982 int16_t *src = (int16_t *)buffer;
5983 int16_t *dst = (int16_t *)buffer;
5984
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005985 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005986 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005987 "out_write called for %s use case with wrong properties",
5988 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005989
5990 /*
5991 * FIXME: this can be removed once audio flinger mixer supports
5992 * mono output
5993 */
5994
5995 /*
5996 * Code below goes over each frame in the buffer and adds both
5997 * L and R samples and then divides by 2 to convert to mono
5998 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005999 if (channel_count == 2) {
6000 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6001 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6002 }
6003 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006004 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006005 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006006
6007 // Note: since out_get_presentation_position() is called alternating with out_write()
6008 // by AudioFlinger, we can check underruns using the prior timestamp read.
6009 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6010 if (out->last_fifo_valid) {
6011 // compute drain to see if there is an underrun.
6012 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
6013 const int64_t frames_by_time =
6014 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
6015 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6016
6017 if (underrun > 0) {
6018 simple_stats_log(&out->fifo_underruns, underrun);
6019
6020 ALOGW("%s: underrun(%lld) "
6021 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6022 __func__,
6023 (long long)out->fifo_underruns.n,
6024 (long long)frames_by_time,
6025 (long long)out->last_fifo_frames_remaining);
6026 }
6027 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6028 }
6029
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306030 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006031
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006032 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006033
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006034 if (out->config.rate)
6035 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6036 out->config.rate;
6037
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006038 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006039 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6040
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006041 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006042 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006043 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306044 out->convert_buffer != NULL) {
6045
6046 memcpy_by_audio_format(out->convert_buffer,
6047 out->hal_op_format,
6048 buffer,
6049 out->hal_ip_format,
6050 out->config.period_size * out->config.channels);
6051
6052 ret = pcm_write(out->pcm, out->convert_buffer,
6053 (out->config.period_size *
6054 out->config.channels *
6055 format_to_bitwidth_table[out->hal_op_format]));
6056 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306057 /*
6058 * To avoid underrun in DSP when the application is not pumping
6059 * data at required rate, check for the no. of bytes and ignore
6060 * pcm_write if it is less than actual buffer size.
6061 * It is a work around to a change in compress VOIP driver.
6062 */
6063 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6064 bytes < (out->config.period_size * out->config.channels *
6065 audio_bytes_per_sample(out->format))) {
6066 size_t voip_buf_size =
6067 out->config.period_size * out->config.channels *
6068 audio_bytes_per_sample(out->format);
6069 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6070 __func__, bytes, voip_buf_size);
6071 usleep(((uint64_t)voip_buf_size - bytes) *
6072 1000000 / audio_stream_out_frame_size(stream) /
6073 out_get_sample_rate(&out->stream.common));
6074 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006075 } else {
6076 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6077 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6078 else
6079 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6080 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306081 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006082
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006083 release_out_focus(out);
6084
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306085 if (ret < 0)
6086 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006087 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306088 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006089 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006090 }
6091
6092exit:
Zhou Songc9672822017-08-16 16:01:39 +08006093 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306094 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306095 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306096 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006097 pthread_mutex_unlock(&out->lock);
6098
6099 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006100 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006101 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306102 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306103 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306104 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306105 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306106 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306107 out->standby = true;
6108 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306109 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006110 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6111 /* prevent division-by-zero */
6112 uint32_t stream_size = audio_stream_out_frame_size(stream);
6113 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006114
Dieter Luecking5d57def2018-09-07 14:23:37 +02006115 if ((stream_size == 0) || (srate == 0)) {
6116 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6117 ATRACE_END();
6118 return -EINVAL;
6119 }
6120 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6121 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006122 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306123 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006124 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006125 return ret;
6126 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006127 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006128 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006129 return bytes;
6130}
6131
6132static int out_get_render_position(const struct audio_stream_out *stream,
6133 uint32_t *dsp_frames)
6134{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006135 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006136
6137 if (dsp_frames == NULL)
6138 return -EINVAL;
6139
6140 *dsp_frames = 0;
6141 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006142 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306143
6144 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6145 * this operation and adev_close_output_stream(where out gets reset).
6146 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306147 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006148 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306149 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006150 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306151 return 0;
6152 }
6153
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006154 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306155 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306156 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006157 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306158 if (ret < 0)
6159 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006160 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306161 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006162 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306163 if (-ENETRESET == ret) {
6164 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306165 out->card_status = CARD_STATUS_OFFLINE;
6166 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306167 } else if(ret < 0) {
6168 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306169 ret = -EINVAL;
6170 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306171 /*
6172 * Handle corner case where compress session is closed during SSR
6173 * and timestamp is queried
6174 */
6175 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306176 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306177 } else if (out->prev_card_status_offline) {
6178 ALOGE("ERROR: previously sound card was offline,return error");
6179 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306180 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306181 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006182 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306183 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306184 pthread_mutex_unlock(&out->lock);
6185 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006186 } else if (audio_is_linear_pcm(out->format)) {
6187 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006188 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006189 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006190 } else
6191 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006192}
6193
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006194static int out_add_audio_effect(const struct audio_stream *stream __unused,
6195 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006196{
6197 return 0;
6198}
6199
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006200static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6201 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006202{
6203 return 0;
6204}
6205
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006206static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6207 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006208{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306209 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006210}
6211
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006212static int out_get_presentation_position(const struct audio_stream_out *stream,
6213 uint64_t *frames, struct timespec *timestamp)
6214{
6215 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306216 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006217 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006218
Ashish Jain5106d362016-05-11 19:23:33 +05306219 /* below piece of code is not guarded against any lock because audioFliner serializes
6220 * this operation and adev_close_output_stream( where out gets reset).
6221 */
6222 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306223 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006224 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306225 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6226 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6227 return 0;
6228 }
6229
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006230 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006231
Ashish Jain5106d362016-05-11 19:23:33 +05306232 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6233 ret = compress_get_tstamp(out->compr, &dsp_frames,
6234 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006235 // Adjustment accounts for A2dp encoder latency with offload usecases
6236 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006237 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006238 unsigned long offset =
6239 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6240 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6241 }
Ashish Jain5106d362016-05-11 19:23:33 +05306242 ALOGVV("%s rendered frames %ld sample_rate %d",
6243 __func__, dsp_frames, out->sample_rate);
6244 *frames = dsp_frames;
6245 if (ret < 0)
6246 ret = -errno;
6247 if (-ENETRESET == ret) {
6248 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306249 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306250 ret = -EINVAL;
6251 } else
6252 ret = 0;
6253 /* this is the best we can do */
6254 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006255 } else {
6256 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006257 unsigned int avail;
6258 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006259 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006260 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006261
Andy Hunga1f48fa2019-07-01 18:14:53 -07006262 if (out->kernel_buffer_size > avail) {
6263 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6264 } else {
6265 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6266 __func__, avail, out->kernel_buffer_size);
6267 avail = out->kernel_buffer_size;
6268 frames_temp = out->last_fifo_frames_remaining = 0;
6269 }
6270 out->last_fifo_valid = true;
6271 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6272
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006273 if (out->written >= frames_temp)
6274 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006275
Andy Hunga1f48fa2019-07-01 18:14:53 -07006276 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6277 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6278
Weiyin Jiangd4633762018-03-16 12:05:03 +08006279 // This adjustment accounts for buffering after app processor.
6280 // It is based on estimated DSP latency per use case, rather than exact.
Robert Lee58215542019-07-15 20:55:12 +08006281 pthread_mutex_lock(&adev->lock);
6282 frames_temp = platform_render_latency(out->dev, out->usecase) *
6283 out->sample_rate / 1000000LL;
6284 pthread_mutex_unlock(&adev->lock);
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006285 if (signed_frames >= frames_temp)
6286 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006287
Weiyin Jiangd4633762018-03-16 12:05:03 +08006288 // Adjustment accounts for A2dp encoder latency with non offload usecases
6289 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006290 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006291 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6292 if (signed_frames >= frames_temp)
6293 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006294 }
6295
6296 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006297 *frames = signed_frames;
6298 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006299 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006300 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6301 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006302 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306303 *frames = out->written;
6304 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306305 if (is_offload_usecase(out->usecase))
6306 ret = -EINVAL;
6307 else
6308 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006309 }
6310 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006311 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006312 return ret;
6313}
6314
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006315static int out_set_callback(struct audio_stream_out *stream,
6316 stream_callback_t callback, void *cookie)
6317{
6318 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006319 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006320
6321 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006322 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006323 out->client_callback = callback;
6324 out->client_cookie = cookie;
6325 if (out->adsp_hdlr_stream_handle) {
6326 ret = audio_extn_adsp_hdlr_stream_set_callback(
6327 out->adsp_hdlr_stream_handle,
6328 callback,
6329 cookie);
6330 if (ret)
6331 ALOGW("%s:adsp hdlr callback registration failed %d",
6332 __func__, ret);
6333 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006334 pthread_mutex_unlock(&out->lock);
6335 return 0;
6336}
6337
6338static int out_pause(struct audio_stream_out* stream)
6339{
6340 struct stream_out *out = (struct stream_out *)stream;
6341 int status = -ENOSYS;
6342 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006343 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006344 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306345 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006346 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006347 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306348 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306349 status = compress_pause(out->compr);
6350
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006351 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006352
Mingming Yin21854652016-04-13 11:54:02 -07006353 if (audio_extn_passthru_is_active()) {
6354 ALOGV("offload use case, pause passthru");
6355 audio_extn_passthru_on_pause(out);
6356 }
6357
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306358 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006359 audio_extn_dts_notify_playback_state(out->usecase, 0,
6360 out->sample_rate, popcount(out->channel_mask),
6361 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006362 }
6363 pthread_mutex_unlock(&out->lock);
6364 }
6365 return status;
6366}
6367
6368static int out_resume(struct audio_stream_out* stream)
6369{
6370 struct stream_out *out = (struct stream_out *)stream;
6371 int status = -ENOSYS;
6372 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006373 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006374 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306375 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006376 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006377 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306378 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306379 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006380 }
6381 if (!status) {
6382 out->offload_state = OFFLOAD_STATE_PLAYING;
6383 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306384 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006385 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6386 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006387 }
6388 pthread_mutex_unlock(&out->lock);
6389 }
6390 return status;
6391}
6392
6393static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6394{
6395 struct stream_out *out = (struct stream_out *)stream;
6396 int status = -ENOSYS;
6397 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006398 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006399 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006400 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6401 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6402 else
6403 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6404 pthread_mutex_unlock(&out->lock);
6405 }
6406 return status;
6407}
6408
6409static int out_flush(struct audio_stream_out* stream)
6410{
6411 struct stream_out *out = (struct stream_out *)stream;
6412 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006413 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006414 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006415 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006416 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6417 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006418 } else {
6419 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6420 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006421 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006422 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006423 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006424 return 0;
6425 }
6426 return -ENOSYS;
6427}
6428
Haynes Mathew George16081042017-05-31 17:16:49 -07006429static int out_stop(const struct audio_stream_out* stream)
6430{
6431 struct stream_out *out = (struct stream_out *)stream;
6432 struct audio_device *adev = out->dev;
6433 int ret = -ENOSYS;
6434
6435 ALOGV("%s", __func__);
6436 pthread_mutex_lock(&adev->lock);
6437 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6438 out->playback_started && out->pcm != NULL) {
6439 pcm_stop(out->pcm);
6440 ret = stop_output_stream(out);
6441 out->playback_started = false;
6442 }
6443 pthread_mutex_unlock(&adev->lock);
6444 return ret;
6445}
6446
6447static int out_start(const struct audio_stream_out* stream)
6448{
6449 struct stream_out *out = (struct stream_out *)stream;
6450 struct audio_device *adev = out->dev;
6451 int ret = -ENOSYS;
6452
6453 ALOGV("%s", __func__);
6454 pthread_mutex_lock(&adev->lock);
6455 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6456 !out->playback_started && out->pcm != NULL) {
6457 ret = start_output_stream(out);
6458 if (ret == 0) {
6459 out->playback_started = true;
6460 }
6461 }
6462 pthread_mutex_unlock(&adev->lock);
6463 return ret;
6464}
6465
6466/*
6467 * Modify config->period_count based on min_size_frames
6468 */
6469static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6470{
6471 int periodCountRequested = (min_size_frames + config->period_size - 1)
6472 / config->period_size;
6473 int periodCount = MMAP_PERIOD_COUNT_MIN;
6474
6475 ALOGV("%s original config.period_size = %d config.period_count = %d",
6476 __func__, config->period_size, config->period_count);
6477
6478 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6479 periodCount *= 2;
6480 }
6481 config->period_count = periodCount;
6482
6483 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6484}
6485
Phil Burkfe17efd2019-03-25 10:23:35 -07006486// Read offset for the positional timestamp from a persistent vendor property.
6487// This is to workaround apparent inaccuracies in the timing information that
6488// is used by the AAudio timing model. The inaccuracies can cause glitches.
6489static int64_t get_mmap_out_time_offset() {
6490 const int32_t kDefaultOffsetMicros = 0;
6491 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006492 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006493 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6494 return mmap_time_offset_micros * (int64_t)1000;
6495}
6496
Haynes Mathew George16081042017-05-31 17:16:49 -07006497static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6498 int32_t min_size_frames,
6499 struct audio_mmap_buffer_info *info)
6500{
6501 struct stream_out *out = (struct stream_out *)stream;
6502 struct audio_device *adev = out->dev;
6503 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006504 unsigned int offset1 = 0;
6505 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006506 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006507 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006508 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006509
Arun Mirpuri5d170872019-03-26 13:21:31 -07006510 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306511 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006512 pthread_mutex_lock(&adev->lock);
6513
Sharad Sanglec6f32552018-05-04 16:15:38 +05306514 if (CARD_STATUS_OFFLINE == out->card_status ||
6515 CARD_STATUS_OFFLINE == adev->card_status) {
6516 ALOGW("out->card_status or adev->card_status offline, try again");
6517 ret = -EIO;
6518 goto exit;
6519 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306520 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006521 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6522 ret = -EINVAL;
6523 goto exit;
6524 }
6525 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6526 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6527 ret = -ENOSYS;
6528 goto exit;
6529 }
6530 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6531 if (out->pcm_device_id < 0) {
6532 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6533 __func__, out->pcm_device_id, out->usecase);
6534 ret = -EINVAL;
6535 goto exit;
6536 }
6537
6538 adjust_mmap_period_count(&out->config, min_size_frames);
6539
Arun Mirpuri5d170872019-03-26 13:21:31 -07006540 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006541 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6542 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6543 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306544 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306545 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6546 out->card_status = CARD_STATUS_OFFLINE;
6547 adev->card_status = CARD_STATUS_OFFLINE;
6548 ret = -EIO;
6549 goto exit;
6550 }
6551
Haynes Mathew George16081042017-05-31 17:16:49 -07006552 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6553 step = "open";
6554 ret = -ENODEV;
6555 goto exit;
6556 }
6557 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6558 if (ret < 0) {
6559 step = "begin";
6560 goto exit;
6561 }
juyuchen626833d2019-06-04 16:48:02 +08006562
6563 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006564 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006565 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006566 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006567 ret = platform_get_mmap_data_fd(adev->platform,
6568 out->pcm_device_id, 0 /*playback*/,
6569 &info->shared_memory_fd,
6570 &mmap_size);
6571 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006572 // Fall back to non exclusive mode
6573 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6574 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006575 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6576 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6577
Arun Mirpuri5d170872019-03-26 13:21:31 -07006578 if (mmap_size < buffer_size) {
6579 step = "mmap";
6580 goto exit;
6581 }
juyuchen626833d2019-06-04 16:48:02 +08006582 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006583 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006584 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006585 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006586
6587 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6588 if (ret < 0) {
6589 step = "commit";
6590 goto exit;
6591 }
6592
Phil Burkfe17efd2019-03-25 10:23:35 -07006593 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6594
Haynes Mathew George16081042017-05-31 17:16:49 -07006595 out->standby = false;
6596 ret = 0;
6597
Arun Mirpuri5d170872019-03-26 13:21:31 -07006598 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006599 __func__, info->shared_memory_address, info->buffer_size_frames);
6600
6601exit:
6602 if (ret != 0) {
6603 if (out->pcm == NULL) {
6604 ALOGE("%s: %s - %d", __func__, step, ret);
6605 } else {
6606 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6607 pcm_close(out->pcm);
6608 out->pcm = NULL;
6609 }
6610 }
6611 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306612 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006613 return ret;
6614}
6615
6616static int out_get_mmap_position(const struct audio_stream_out *stream,
6617 struct audio_mmap_position *position)
6618{
6619 struct stream_out *out = (struct stream_out *)stream;
6620 ALOGVV("%s", __func__);
6621 if (position == NULL) {
6622 return -EINVAL;
6623 }
6624 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006625 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006626 return -ENOSYS;
6627 }
6628 if (out->pcm == NULL) {
6629 return -ENOSYS;
6630 }
6631
6632 struct timespec ts = { 0, 0 };
6633 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6634 if (ret < 0) {
6635 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6636 return ret;
6637 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006638 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6639 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006640 return 0;
6641}
6642
6643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006644/** audio_stream_in implementation **/
6645static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6646{
6647 struct stream_in *in = (struct stream_in *)stream;
6648
6649 return in->config.rate;
6650}
6651
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006652static int in_set_sample_rate(struct audio_stream *stream __unused,
6653 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006654{
6655 return -ENOSYS;
6656}
6657
6658static size_t in_get_buffer_size(const struct audio_stream *stream)
6659{
6660 struct stream_in *in = (struct stream_in *)stream;
6661
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006662 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6663 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006664 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6665 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306666 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306667 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006668
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006669 return in->config.period_size * in->af_period_multiplier *
6670 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006671}
6672
6673static uint32_t in_get_channels(const struct audio_stream *stream)
6674{
6675 struct stream_in *in = (struct stream_in *)stream;
6676
6677 return in->channel_mask;
6678}
6679
6680static audio_format_t in_get_format(const struct audio_stream *stream)
6681{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006682 struct stream_in *in = (struct stream_in *)stream;
6683
6684 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006685}
6686
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006687static int in_set_format(struct audio_stream *stream __unused,
6688 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006689{
6690 return -ENOSYS;
6691}
6692
6693static int in_standby(struct audio_stream *stream)
6694{
6695 struct stream_in *in = (struct stream_in *)stream;
6696 struct audio_device *adev = in->dev;
6697 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306698 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6699 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006700 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306701
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006702 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006703 if (!in->standby && in->is_st_session) {
6704 ALOGD("%s: sound trigger pcm stop lab", __func__);
6705 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006706 if (adev->num_va_sessions > 0)
6707 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006708 in->standby = 1;
6709 }
6710
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006711 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006712 if (adev->adm_deregister_stream)
6713 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6714
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006715 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006716 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006717 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006718 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006719 voice_extn_compress_voip_close_input_stream(stream);
6720 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006721 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6722 do_stop = in->capture_started;
6723 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006724 if (in->mmap_shared_memory_fd >= 0) {
6725 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6726 __func__, in->mmap_shared_memory_fd);
6727 close(in->mmap_shared_memory_fd);
6728 in->mmap_shared_memory_fd = -1;
6729 }
Zhou Songa8895042016-07-05 17:54:22 +08006730 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306731 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306732 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006733 }
6734
Arun Mirpuri5d170872019-03-26 13:21:31 -07006735 if (in->pcm) {
6736 ATRACE_BEGIN("pcm_in_close");
6737 pcm_close(in->pcm);
6738 ATRACE_END();
6739 in->pcm = NULL;
6740 }
6741
Carter Hsu2e429db2019-05-14 18:50:52 +08006742 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006743 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006744
George Gao3018ede2019-10-23 13:23:00 -07006745 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6746 if (adev->num_va_sessions > 0)
6747 adev->num_va_sessions--;
6748 }
Quinn Malef6050362019-01-30 15:55:40 -08006749
Eric Laurent150dbfe2013-02-27 14:31:02 -08006750 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006751 }
6752 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006753 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006754 return status;
6755}
6756
Aalique Grahame22e49102018-12-18 14:23:57 -08006757static int in_dump(const struct audio_stream *stream,
6758 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006759{
Aalique Grahame22e49102018-12-18 14:23:57 -08006760 struct stream_in *in = (struct stream_in *)stream;
6761
6762 // We try to get the lock for consistency,
6763 // but it isn't necessary for these variables.
6764 // If we're not in standby, we may be blocked on a read.
6765 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6766 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6767 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6768 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6769
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006770 char buffer[256]; // for statistics formatting
6771 if (in->start_latency_ms.n > 0) {
6772 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6773 dprintf(fd, " Start latency ms: %s\n", buffer);
6774 }
6775
Aalique Grahame22e49102018-12-18 14:23:57 -08006776 if (locked) {
6777 pthread_mutex_unlock(&in->lock);
6778 }
6779
6780 // dump error info
6781 (void)error_log_dump(
6782 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006784 return 0;
6785}
6786
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306787static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6788{
6789 if (!stream || !parms)
6790 return;
6791
6792 struct stream_in *in = (struct stream_in *)stream;
6793 struct audio_device *adev = in->dev;
6794
6795 card_status_t status;
6796 int card;
6797 if (parse_snd_card_status(parms, &card, &status) < 0)
6798 return;
6799
6800 pthread_mutex_lock(&adev->lock);
6801 bool valid_cb = (card == adev->snd_card);
6802 pthread_mutex_unlock(&adev->lock);
6803
6804 if (!valid_cb)
6805 return;
6806
6807 lock_input_stream(in);
6808 if (in->card_status != status)
6809 in->card_status = status;
6810 pthread_mutex_unlock(&in->lock);
6811
6812 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6813 use_case_table[in->usecase],
6814 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6815
6816 // a better solution would be to report error back to AF and let
6817 // it put the stream to standby
6818 if (status == CARD_STATUS_OFFLINE)
6819 in_standby(&in->stream.common);
6820
6821 return;
6822}
6823
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006824int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006825 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006826 audio_source_t source)
6827{
6828 struct audio_device *adev = in->dev;
6829 int ret = 0;
6830
6831 lock_input_stream(in);
6832 pthread_mutex_lock(&adev->lock);
6833
6834 /* no audio source uses val == 0 */
6835 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6836 in->source = source;
6837 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6838 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6839 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6840 (in->config.rate == 8000 || in->config.rate == 16000 ||
6841 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6842 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6843 ret = voice_extn_compress_voip_open_input_stream(in);
6844 if (ret != 0) {
6845 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6846 __func__, ret);
6847 }
6848 }
6849 }
6850
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006851 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6852 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006853 // Workaround: If routing to an non existing usb device, fail gracefully
6854 // The routing request will otherwise block during 10 second
6855 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006856 struct str_parms *usb_addr =
6857 str_parms_create_str(get_usb_device_address(devices));
6858 if (is_usb_in_device_type(devices) && usb_addr &&
6859 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006860 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6861 ret = -ENOSYS;
6862 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006863 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006864 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006865 if (!in->standby && !in->is_st_session) {
6866 ALOGV("update input routing change");
6867 // inform adm before actual routing to prevent glitches.
6868 if (adev->adm_on_routing_change) {
6869 adev->adm_on_routing_change(adev->adm_data,
6870 in->capture_handle);
6871 ret = select_devices(adev, in->usecase);
6872 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6873 adev->adm_routing_changed = true;
6874 }
6875 }
6876 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006877 if (usb_addr)
6878 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006879 }
6880 pthread_mutex_unlock(&adev->lock);
6881 pthread_mutex_unlock(&in->lock);
6882
6883 ALOGD("%s: exit: status(%d)", __func__, ret);
6884 return ret;
6885}
6886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006887static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6888{
6889 struct stream_in *in = (struct stream_in *)stream;
6890 struct audio_device *adev = in->dev;
6891 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006892 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306893 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006894
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306895 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006896 parms = str_parms_create_str(kvpairs);
6897
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306898 if (!parms)
6899 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006900 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006901 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006902
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306903 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6904 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306905 strlcpy(in->profile, value, sizeof(in->profile));
6906 ALOGV("updating stream profile with value '%s'", in->profile);
6907 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6908 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006909 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306910 in->sample_rate, in->bit_width,
6911 in->profile, &in->app_type_cfg);
6912 }
6913
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006914 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006915 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006916
6917 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306918error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306919 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006920}
6921
6922static char* in_get_parameters(const struct audio_stream *stream,
6923 const char *keys)
6924{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006925 struct stream_in *in = (struct stream_in *)stream;
6926 struct str_parms *query = str_parms_create_str(keys);
6927 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006928 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006929
6930 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006931 if (reply) {
6932 str_parms_destroy(reply);
6933 }
6934 if (query) {
6935 str_parms_destroy(query);
6936 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006937 ALOGE("in_get_parameters: failed to create query or reply");
6938 return NULL;
6939 }
6940
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006941 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006942
6943 voice_extn_in_get_parameters(in, query, reply);
6944
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006945 stream_get_parameter_channels(query, reply,
6946 &in->supported_channel_masks[0]);
6947 stream_get_parameter_formats(query, reply,
6948 &in->supported_formats[0]);
6949 stream_get_parameter_rates(query, reply,
6950 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006951 str = str_parms_to_str(reply);
6952 str_parms_destroy(query);
6953 str_parms_destroy(reply);
6954
6955 ALOGV("%s: exit: returns - %s", __func__, str);
6956 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006957}
6958
Aalique Grahame22e49102018-12-18 14:23:57 -08006959static int in_set_gain(struct audio_stream_in *stream,
6960 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006961{
Aalique Grahame22e49102018-12-18 14:23:57 -08006962 struct stream_in *in = (struct stream_in *)stream;
6963 char mixer_ctl_name[128];
6964 struct mixer_ctl *ctl;
6965 int ctl_value;
6966
6967 ALOGV("%s: gain %f", __func__, gain);
6968
6969 if (stream == NULL)
6970 return -EINVAL;
6971
6972 /* in_set_gain() only used to silence MMAP capture for now */
6973 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6974 return -ENOSYS;
6975
6976 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6977
6978 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6979 if (!ctl) {
6980 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6981 __func__, mixer_ctl_name);
6982 return -ENOSYS;
6983 }
6984
6985 if (gain < RECORD_GAIN_MIN)
6986 gain = RECORD_GAIN_MIN;
6987 else if (gain > RECORD_GAIN_MAX)
6988 gain = RECORD_GAIN_MAX;
6989 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6990
6991 mixer_ctl_set_value(ctl, 0, ctl_value);
6992
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006993 return 0;
6994}
6995
6996static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6997 size_t bytes)
6998{
6999 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307000
7001 if (in == NULL) {
7002 ALOGE("%s: stream_in ptr is NULL", __func__);
7003 return -EINVAL;
7004 }
7005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007006 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307007 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307008 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007009
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007010 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307011
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007012 if (in->is_st_session) {
7013 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7014 /* Read from sound trigger HAL */
7015 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007016 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007017 if (adev->num_va_sessions < UINT_MAX)
7018 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007019 in->standby = 0;
7020 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007021 pthread_mutex_unlock(&in->lock);
7022 return bytes;
7023 }
7024
Haynes Mathew George16081042017-05-31 17:16:49 -07007025 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7026 ret = -ENOSYS;
7027 goto exit;
7028 }
7029
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007030 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7031 !in->standby && adev->adm_routing_changed) {
7032 ret = -ENOSYS;
7033 goto exit;
7034 }
7035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007036 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007037 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7038
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007039 pthread_mutex_lock(&adev->lock);
7040 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7041 ret = voice_extn_compress_voip_start_input_stream(in);
7042 else
7043 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007044 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7045 if (adev->num_va_sessions < UINT_MAX)
7046 adev->num_va_sessions++;
7047 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007048 pthread_mutex_unlock(&adev->lock);
7049 if (ret != 0) {
7050 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007051 }
7052 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007053
7054 // log startup time in ms.
7055 simple_stats_log(
7056 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007057 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007058
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307059 /* Avoid read if capture_stopped is set */
7060 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7061 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7062 ret = -EINVAL;
7063 goto exit;
7064 }
7065
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007066 // what's the duration requested by the client?
7067 long ns = 0;
7068
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307069 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007070 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7071 in->config.rate;
7072
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007073 ret = request_in_focus(in, ns);
7074 if (ret != 0)
7075 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007076 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007077
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307078 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307079 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7080 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307081 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007082 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307083 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007084 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007085 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007086 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007087 } else if (audio_extn_ffv_get_stream() == in) {
7088 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307089 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007090 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307091 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7092 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7093 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7094 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307095 ret = -EINVAL;
7096 goto exit;
7097 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307098 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307099 ret = -errno;
7100 }
7101 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307102 /* bytes read is always set to bytes for non compress usecases */
7103 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007104 }
7105
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007106 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007108 /*
Quinn Malef6050362019-01-30 15:55:40 -08007109 * Instead of writing zeroes here, we could trust the hardware to always
7110 * provide zeroes when muted. This is also muted with voice recognition
7111 * usecases so that other clients do not have access to voice recognition
7112 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007113 */
Quinn Malef6050362019-01-30 15:55:40 -08007114 if ((ret == 0 && voice_get_mic_mute(adev) &&
7115 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007116 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7117 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007118 (adev->num_va_sessions &&
7119 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7120 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7121 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007122 memset(buffer, 0, bytes);
7123
7124exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307125 frame_size = audio_stream_in_frame_size(stream);
7126 if (frame_size > 0)
7127 in->frames_read += bytes_read/frame_size;
7128
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007129 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307130 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007131 pthread_mutex_unlock(&in->lock);
7132
7133 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307134 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307135 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307136 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307137 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307138 in->standby = true;
7139 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307140 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307141 bytes_read = bytes;
7142 memset(buffer, 0, bytes);
7143 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007144 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007145 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7146 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007147 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307148 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307149 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007150 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307151 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007152}
7153
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007154static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007155{
7156 return 0;
7157}
7158
Aalique Grahame22e49102018-12-18 14:23:57 -08007159static int in_get_capture_position(const struct audio_stream_in *stream,
7160 int64_t *frames, int64_t *time)
7161{
7162 if (stream == NULL || frames == NULL || time == NULL) {
7163 return -EINVAL;
7164 }
7165 struct stream_in *in = (struct stream_in *)stream;
7166 int ret = -ENOSYS;
7167
7168 lock_input_stream(in);
7169 // note: ST sessions do not close the alsa pcm driver synchronously
7170 // on standby. Therefore, we may return an error even though the
7171 // pcm stream is still opened.
7172 if (in->standby) {
7173 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7174 "%s stream in standby but pcm not NULL for non ST session", __func__);
7175 goto exit;
7176 }
7177 if (in->pcm) {
7178 struct timespec timestamp;
7179 unsigned int avail;
7180 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7181 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007182 pthread_mutex_lock(&adev->lock);
7183 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
7184 - platform_capture_latency(in->dev, in->usecase) * 1000LL;
7185 pthread_mutex_unlock(&adev->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08007186 ret = 0;
7187 }
7188 }
7189exit:
7190 pthread_mutex_unlock(&in->lock);
7191 return ret;
7192}
7193
Carter Hsu2e429db2019-05-14 18:50:52 +08007194static int in_update_effect_list(bool add, effect_handle_t effect,
7195 struct listnode *head)
7196{
7197 struct listnode *node;
7198 struct in_effect_list *elist = NULL;
7199 struct in_effect_list *target = NULL;
7200 int ret = 0;
7201
7202 if (!head)
7203 return ret;
7204
7205 list_for_each(node, head) {
7206 elist = node_to_item(node, struct in_effect_list, list);
7207 if (elist->handle == effect) {
7208 target = elist;
7209 break;
7210 }
7211 }
7212
7213 if (add) {
7214 if (target) {
7215 ALOGD("effect %p already exist", effect);
7216 return ret;
7217 }
7218
7219 target = (struct in_effect_list *)
7220 calloc(1, sizeof(struct in_effect_list));
7221
7222 if (!target) {
7223 ALOGE("%s:fail to allocate memory", __func__);
7224 return -ENOMEM;
7225 }
7226
7227 target->handle = effect;
7228 list_add_tail(head, &target->list);
7229 } else {
7230 if (target) {
7231 list_remove(&target->list);
7232 free(target);
7233 }
7234 }
7235
7236 return ret;
7237}
7238
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007239static int add_remove_audio_effect(const struct audio_stream *stream,
7240 effect_handle_t effect,
7241 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007242{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007243 struct stream_in *in = (struct stream_in *)stream;
7244 int status = 0;
7245 effect_descriptor_t desc;
7246
7247 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007248 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7249
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007250 if (status != 0)
7251 return status;
7252
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007253 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007254 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007255 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007256 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7257 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007258 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007259
7260 in_update_effect_list(enable, effect, &in->aec_list);
7261 enable = !list_empty(&in->aec_list);
7262 if (enable == in->enable_aec)
7263 goto exit;
7264
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007265 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007266 ALOGD("AEC enable %d", enable);
7267
Aalique Grahame22e49102018-12-18 14:23:57 -08007268 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7269 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7270 in->dev->enable_voicerx = enable;
7271 struct audio_usecase *usecase;
7272 struct listnode *node;
7273 list_for_each(node, &in->dev->usecase_list) {
7274 usecase = node_to_item(node, struct audio_usecase, list);
7275 if (usecase->type == PCM_PLAYBACK)
7276 select_devices(in->dev, usecase->id);
7277 }
7278 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007279 if (!in->standby) {
7280 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7281 select_devices(in->dev, in->usecase);
7282 }
7283
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007284 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007285 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7286
7287 in_update_effect_list(enable, effect, &in->ns_list);
7288 enable = !list_empty(&in->ns_list);
7289 if (enable == in->enable_ns)
7290 goto exit;
7291
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007292 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007293 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007294 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007295 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7296 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007297 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7298 select_devices(in->dev, in->usecase);
7299 } else
7300 select_devices(in->dev, in->usecase);
7301 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007302 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007303exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007304 pthread_mutex_unlock(&in->dev->lock);
7305 pthread_mutex_unlock(&in->lock);
7306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007307 return 0;
7308}
7309
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007310static int in_add_audio_effect(const struct audio_stream *stream,
7311 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007312{
Eric Laurent994a6932013-07-17 11:51:42 -07007313 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007314 return add_remove_audio_effect(stream, effect, true);
7315}
7316
7317static int in_remove_audio_effect(const struct audio_stream *stream,
7318 effect_handle_t effect)
7319{
Eric Laurent994a6932013-07-17 11:51:42 -07007320 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007321 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007322}
7323
Derek Chenf939fb72018-11-13 13:34:41 -08007324streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7325 audio_io_handle_t input)
7326{
7327 struct listnode *node;
7328
7329 list_for_each(node, &dev->active_inputs_list) {
7330 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7331 streams_input_ctxt_t,
7332 list);
7333 if (in_ctxt->input->capture_handle == input) {
7334 return in_ctxt;
7335 }
7336 }
7337 return NULL;
7338}
7339
7340streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7341 audio_io_handle_t output)
7342{
7343 struct listnode *node;
7344
7345 list_for_each(node, &dev->active_outputs_list) {
7346 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7347 streams_output_ctxt_t,
7348 list);
7349 if (out_ctxt->output->handle == output) {
7350 return out_ctxt;
7351 }
7352 }
7353 return NULL;
7354}
7355
Haynes Mathew George16081042017-05-31 17:16:49 -07007356static int in_stop(const struct audio_stream_in* stream)
7357{
7358 struct stream_in *in = (struct stream_in *)stream;
7359 struct audio_device *adev = in->dev;
7360
7361 int ret = -ENOSYS;
7362 ALOGV("%s", __func__);
7363 pthread_mutex_lock(&adev->lock);
7364 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7365 in->capture_started && in->pcm != NULL) {
7366 pcm_stop(in->pcm);
7367 ret = stop_input_stream(in);
7368 in->capture_started = false;
7369 }
7370 pthread_mutex_unlock(&adev->lock);
7371 return ret;
7372}
7373
7374static int in_start(const struct audio_stream_in* stream)
7375{
7376 struct stream_in *in = (struct stream_in *)stream;
7377 struct audio_device *adev = in->dev;
7378 int ret = -ENOSYS;
7379
7380 ALOGV("%s in %p", __func__, in);
7381 pthread_mutex_lock(&adev->lock);
7382 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7383 !in->capture_started && in->pcm != NULL) {
7384 if (!in->capture_started) {
7385 ret = start_input_stream(in);
7386 if (ret == 0) {
7387 in->capture_started = true;
7388 }
7389 }
7390 }
7391 pthread_mutex_unlock(&adev->lock);
7392 return ret;
7393}
7394
Phil Burke0a86d12019-02-16 22:28:11 -08007395// Read offset for the positional timestamp from a persistent vendor property.
7396// This is to workaround apparent inaccuracies in the timing information that
7397// is used by the AAudio timing model. The inaccuracies can cause glitches.
7398static int64_t in_get_mmap_time_offset() {
7399 const int32_t kDefaultOffsetMicros = 0;
7400 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007401 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007402 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7403 return mmap_time_offset_micros * (int64_t)1000;
7404}
7405
Haynes Mathew George16081042017-05-31 17:16:49 -07007406static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7407 int32_t min_size_frames,
7408 struct audio_mmap_buffer_info *info)
7409{
7410 struct stream_in *in = (struct stream_in *)stream;
7411 struct audio_device *adev = in->dev;
7412 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007413 unsigned int offset1 = 0;
7414 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007415 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007416 uint32_t mmap_size = 0;
7417 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007418
7419 pthread_mutex_lock(&adev->lock);
7420 ALOGV("%s in %p", __func__, in);
7421
Sharad Sanglec6f32552018-05-04 16:15:38 +05307422 if (CARD_STATUS_OFFLINE == in->card_status||
7423 CARD_STATUS_OFFLINE == adev->card_status) {
7424 ALOGW("in->card_status or adev->card_status offline, try again");
7425 ret = -EIO;
7426 goto exit;
7427 }
7428
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307429 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007430 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7431 ret = -EINVAL;
7432 goto exit;
7433 }
7434 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7435 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7436 ALOGV("%s in %p", __func__, in);
7437 ret = -ENOSYS;
7438 goto exit;
7439 }
7440 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7441 if (in->pcm_device_id < 0) {
7442 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7443 __func__, in->pcm_device_id, in->usecase);
7444 ret = -EINVAL;
7445 goto exit;
7446 }
7447
7448 adjust_mmap_period_count(&in->config, min_size_frames);
7449
7450 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7451 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7452 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7453 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307454 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307455 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7456 in->card_status = CARD_STATUS_OFFLINE;
7457 adev->card_status = CARD_STATUS_OFFLINE;
7458 ret = -EIO;
7459 goto exit;
7460 }
7461
Haynes Mathew George16081042017-05-31 17:16:49 -07007462 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7463 step = "open";
7464 ret = -ENODEV;
7465 goto exit;
7466 }
7467
7468 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7469 if (ret < 0) {
7470 step = "begin";
7471 goto exit;
7472 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007473
juyuchen626833d2019-06-04 16:48:02 +08007474 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007475 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7476 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7477 info->burst_size_frames = in->config.period_size;
7478 ret = platform_get_mmap_data_fd(adev->platform,
7479 in->pcm_device_id, 1 /*capture*/,
7480 &info->shared_memory_fd,
7481 &mmap_size);
7482 if (ret < 0) {
7483 // Fall back to non exclusive mode
7484 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7485 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007486 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7487 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7488
Arun Mirpuri5d170872019-03-26 13:21:31 -07007489 if (mmap_size < buffer_size) {
7490 step = "mmap";
7491 goto exit;
7492 }
juyuchen626833d2019-06-04 16:48:02 +08007493 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007494 }
7495
7496 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007497
7498 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7499 if (ret < 0) {
7500 step = "commit";
7501 goto exit;
7502 }
7503
Phil Burke0a86d12019-02-16 22:28:11 -08007504 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7505
Haynes Mathew George16081042017-05-31 17:16:49 -07007506 in->standby = false;
7507 ret = 0;
7508
7509 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7510 __func__, info->shared_memory_address, info->buffer_size_frames);
7511
7512exit:
7513 if (ret != 0) {
7514 if (in->pcm == NULL) {
7515 ALOGE("%s: %s - %d", __func__, step, ret);
7516 } else {
7517 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7518 pcm_close(in->pcm);
7519 in->pcm = NULL;
7520 }
7521 }
7522 pthread_mutex_unlock(&adev->lock);
7523 return ret;
7524}
7525
7526static int in_get_mmap_position(const struct audio_stream_in *stream,
7527 struct audio_mmap_position *position)
7528{
7529 struct stream_in *in = (struct stream_in *)stream;
7530 ALOGVV("%s", __func__);
7531 if (position == NULL) {
7532 return -EINVAL;
7533 }
7534 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7535 return -ENOSYS;
7536 }
7537 if (in->pcm == NULL) {
7538 return -ENOSYS;
7539 }
7540 struct timespec ts = { 0, 0 };
7541 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7542 if (ret < 0) {
7543 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7544 return ret;
7545 }
Phil Burke0a86d12019-02-16 22:28:11 -08007546 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7547 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007548 return 0;
7549}
7550
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307551static int in_get_active_microphones(const struct audio_stream_in *stream,
7552 struct audio_microphone_characteristic_t *mic_array,
7553 size_t *mic_count) {
7554 struct stream_in *in = (struct stream_in *)stream;
7555 struct audio_device *adev = in->dev;
7556 ALOGVV("%s", __func__);
7557
7558 lock_input_stream(in);
7559 pthread_mutex_lock(&adev->lock);
7560 int ret = platform_get_active_microphones(adev->platform,
7561 audio_channel_count_from_in_mask(in->channel_mask),
7562 in->usecase, mic_array, mic_count);
7563 pthread_mutex_unlock(&adev->lock);
7564 pthread_mutex_unlock(&in->lock);
7565
7566 return ret;
7567}
7568
7569static int adev_get_microphones(const struct audio_hw_device *dev,
7570 struct audio_microphone_characteristic_t *mic_array,
7571 size_t *mic_count) {
7572 struct audio_device *adev = (struct audio_device *)dev;
7573 ALOGVV("%s", __func__);
7574
7575 pthread_mutex_lock(&adev->lock);
7576 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7577 pthread_mutex_unlock(&adev->lock);
7578
7579 return ret;
7580}
juyuchendb308c22019-01-21 11:57:17 -07007581
7582static void in_update_sink_metadata(struct audio_stream_in *stream,
7583 const struct sink_metadata *sink_metadata) {
7584
7585 if (stream == NULL
7586 || sink_metadata == NULL
7587 || sink_metadata->tracks == NULL) {
7588 return;
7589 }
7590
7591 int error = 0;
7592 struct stream_in *in = (struct stream_in *)stream;
7593 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007594 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007595 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007596
7597 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007598
7599 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007600 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007601
7602 lock_input_stream(in);
7603 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007604 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007605
Zhou Song62ea0282020-03-22 19:53:01 +08007606 is_ha_usecase = adev->ha_proxy_enable ?
7607 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7608 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7609 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007610 && adev->voice_tx_output != NULL) {
7611 /* Use the rx device from afe-proxy record to route voice call because
7612 there is no routing if tx device is on primary hal and rx device
7613 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007614 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007615
7616 if (!voice_is_call_state_active(adev)) {
7617 if (adev->mode == AUDIO_MODE_IN_CALL) {
7618 adev->current_call_output = adev->voice_tx_output;
7619 error = voice_start_call(adev);
7620 if (error != 0)
7621 ALOGE("%s: start voice call failed %d", __func__, error);
7622 }
7623 } else {
7624 adev->current_call_output = adev->voice_tx_output;
7625 voice_update_devices_for_all_voice_usecases(adev);
7626 }
7627 }
7628
7629 pthread_mutex_unlock(&adev->lock);
7630 pthread_mutex_unlock(&in->lock);
7631}
7632
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307633int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007634 audio_io_handle_t handle,
7635 audio_devices_t devices,
7636 audio_output_flags_t flags,
7637 struct audio_config *config,
7638 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007639 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007640{
7641 struct audio_device *adev = (struct audio_device *)dev;
7642 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307643 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007644 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007645 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307646 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007647 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7648 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7649 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7650 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007651 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007652 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7653 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007654 bool force_haptic_path =
7655 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007656 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007657
kunleizdff872d2018-08-20 14:40:33 +08007658 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007659 is_usb_dev = false;
7660 devices = AUDIO_DEVICE_OUT_SPEAKER;
7661 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7662 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007663 if (config->format == AUDIO_FORMAT_DEFAULT)
7664 config->format = AUDIO_FORMAT_PCM_16_BIT;
7665 if (config->sample_rate == 0)
7666 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7667 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7668 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007669 }
7670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007671 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307672
Rahul Sharma99770982019-03-06 17:05:26 +05307673 pthread_mutex_lock(&adev->lock);
7674 if (out_get_stream(adev, handle) != NULL) {
7675 ALOGW("%s, output stream already opened", __func__);
7676 ret = -EEXIST;
7677 }
7678 pthread_mutex_unlock(&adev->lock);
7679 if (ret)
7680 return ret;
7681
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007682 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7683
Mingming Yin3a941d42016-02-17 18:08:05 -08007684 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007685 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7686 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307687
7688
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007689 if (!out) {
7690 return -ENOMEM;
7691 }
7692
Haynes Mathew George204045b2015-02-25 20:32:03 -08007693 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007694 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307695 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007696 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007697 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007699 if (devices == AUDIO_DEVICE_NONE)
7700 devices = AUDIO_DEVICE_OUT_SPEAKER;
7701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007702 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007703 list_init(&out->device_list);
7704 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007705 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007706 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007707 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307708 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307709 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7710 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7711 else
7712 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007713 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007714 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007715 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307716 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307717 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307718 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007719 out->hal_output_suspend_supported = 0;
7720 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307721 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307722 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307723 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007724 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007725
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307726 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307727 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007728 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7729
Aalique Grahame22e49102018-12-18 14:23:57 -08007730 if (direct_dev &&
7731 (audio_is_linear_pcm(out->format) ||
7732 config->format == AUDIO_FORMAT_DEFAULT) &&
7733 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7734 audio_format_t req_format = config->format;
7735 audio_channel_mask_t req_channel_mask = config->channel_mask;
7736 uint32_t req_sample_rate = config->sample_rate;
7737
7738 pthread_mutex_lock(&adev->lock);
7739 if (is_hdmi) {
7740 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7741 ret = read_hdmi_sink_caps(out);
7742 if (config->sample_rate == 0)
7743 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7744 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7745 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7746 if (config->format == AUDIO_FORMAT_DEFAULT)
7747 config->format = AUDIO_FORMAT_PCM_16_BIT;
7748 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007749 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7750 &config->format,
7751 &out->supported_formats[0],
7752 MAX_SUPPORTED_FORMATS,
7753 &config->channel_mask,
7754 &out->supported_channel_masks[0],
7755 MAX_SUPPORTED_CHANNEL_MASKS,
7756 &config->sample_rate,
7757 &out->supported_sample_rates[0],
7758 MAX_SUPPORTED_SAMPLE_RATES);
7759 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007760 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007761
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007762 pthread_mutex_unlock(&adev->lock);
7763 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007764 if (ret == -ENOSYS) {
7765 /* ignore and go with default */
7766 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007767 }
7768 // For MMAP NO IRQ, allow conversions in ADSP
7769 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7770 goto error_open;
7771 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007772 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007773 goto error_open;
7774 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007775
7776 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7777 config->sample_rate = req_sample_rate;
7778 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7779 config->channel_mask = req_channel_mask;
7780 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7781 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007782 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007783
7784 out->sample_rate = config->sample_rate;
7785 out->channel_mask = config->channel_mask;
7786 out->format = config->format;
7787 if (is_hdmi) {
7788 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7789 out->config = pcm_config_hdmi_multi;
7790 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7791 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7792 out->config = pcm_config_mmap_playback;
7793 out->stream.start = out_start;
7794 out->stream.stop = out_stop;
7795 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7796 out->stream.get_mmap_position = out_get_mmap_position;
7797 } else {
7798 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7799 out->config = pcm_config_hifi;
7800 }
7801
7802 out->config.rate = out->sample_rate;
7803 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7804 if (is_hdmi) {
7805 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7806 audio_bytes_per_sample(out->format));
7807 }
7808 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007809 }
7810
Derek Chenf6318be2017-06-12 17:16:24 -04007811 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007812 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007813 /* extract car audio stream index */
7814 out->car_audio_stream =
7815 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7816 if (out->car_audio_stream < 0) {
7817 ALOGE("%s: invalid car audio stream %x",
7818 __func__, out->car_audio_stream);
7819 ret = -EINVAL;
7820 goto error_open;
7821 }
Derek Chen5f67a942020-02-24 23:08:13 -08007822 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007823 }
7824
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007825 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007826 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007827 if (!voice_extn_is_compress_voip_supported()) {
7828 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7829 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007830 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7831 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007832 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7833 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007834 out->volume_l = INVALID_OUT_VOLUME;
7835 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007836
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007837 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007838 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007839 uint32_t channel_count =
7840 audio_channel_count_from_out_mask(out->channel_mask);
7841 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7842 out->sample_rate, out->format,
7843 channel_count, false);
7844 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7845 if (frame_size != 0)
7846 out->config.period_size = buffer_size / frame_size;
7847 else
7848 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007849 }
7850 } else {
7851 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7852 voice_extn_compress_voip_is_active(out->dev)) &&
7853 (voice_extn_compress_voip_is_config_supported(config))) {
7854 ret = voice_extn_compress_voip_open_output_stream(out);
7855 if (ret != 0) {
7856 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7857 __func__, ret);
7858 goto error_open;
7859 }
Sujin Panicker19027262019-09-16 18:28:06 +05307860 } else {
7861 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7862 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007863 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007864 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007865 } else if (audio_is_linear_pcm(out->format) &&
7866 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7867 out->channel_mask = config->channel_mask;
7868 out->sample_rate = config->sample_rate;
7869 out->format = config->format;
7870 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7871 // does this change?
7872 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7873 out->config.rate = config->sample_rate;
7874 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7875 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7876 audio_bytes_per_sample(config->format));
7877 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007878 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307879 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307880 pthread_mutex_lock(&adev->lock);
7881 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7882 pthread_mutex_unlock(&adev->lock);
7883
7884 // reject offload during card offline to allow
7885 // fallback to s/w paths
7886 if (offline) {
7887 ret = -ENODEV;
7888 goto error_open;
7889 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007890
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007891 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7892 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7893 ALOGE("%s: Unsupported Offload information", __func__);
7894 ret = -EINVAL;
7895 goto error_open;
7896 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007897
Atul Khare3fa6e542017-08-09 00:56:17 +05307898 if (config->offload_info.format == 0)
7899 config->offload_info.format = config->format;
7900 if (config->offload_info.sample_rate == 0)
7901 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007902
Mingming Yin90310102013-11-13 16:57:00 -08007903 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307904 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007905 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007906 ret = -EINVAL;
7907 goto error_open;
7908 }
7909
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007910 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7911 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7912 (audio_extn_passthru_is_passthrough_stream(out)) &&
7913 !((config->sample_rate == 48000) ||
7914 (config->sample_rate == 96000) ||
7915 (config->sample_rate == 192000))) {
7916 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7917 __func__, config->sample_rate, config->offload_info.format);
7918 ret = -EINVAL;
7919 goto error_open;
7920 }
7921
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007922 out->compr_config.codec = (struct snd_codec *)
7923 calloc(1, sizeof(struct snd_codec));
7924
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007925 if (!out->compr_config.codec) {
7926 ret = -ENOMEM;
7927 goto error_open;
7928 }
7929
Dhananjay Kumarac341582017-02-23 23:42:25 +05307930 out->stream.pause = out_pause;
7931 out->stream.resume = out_resume;
7932 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307933 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307934 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007935 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307936 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007937 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307938 } else {
7939 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7940 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007941 }
vivek mehta446c3962015-09-14 10:57:35 -07007942
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307943 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7944 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007945#ifdef AUDIO_GKI_ENABLED
7946 /* out->compr_config.codec->reserved[1] is for flags */
7947 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7948#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307949 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007950#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307951 }
7952
vivek mehta446c3962015-09-14 10:57:35 -07007953 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007954 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007955 config->format == 0 && config->sample_rate == 0 &&
7956 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007957 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007958 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7959 } else {
7960 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7961 ret = -EEXIST;
7962 goto error_open;
7963 }
vivek mehta446c3962015-09-14 10:57:35 -07007964 }
7965
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007966 if (config->offload_info.channel_mask)
7967 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007968 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007969 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007970 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007971 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307972 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007973 ret = -EINVAL;
7974 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007975 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007976
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007977 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007978 out->sample_rate = config->offload_info.sample_rate;
7979
Mingming Yin3ee55c62014-08-04 14:23:35 -07007980 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007981
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307982 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307983 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307984 audio_extn_dolby_send_ddp_endp_params(adev);
7985 audio_extn_dolby_set_dmid(adev);
7986 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007987
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007988 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007989 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007990 out->compr_config.codec->bit_rate =
7991 config->offload_info.bit_rate;
7992 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307993 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007994 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307995 /* Update bit width only for non passthrough usecases.
7996 * For passthrough usecases, the output will always be opened @16 bit
7997 */
7998 if (!audio_extn_passthru_is_passthrough_stream(out))
7999 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308000
8001 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008002#ifdef AUDIO_GKI_ENABLED
8003 /* out->compr_config.codec->reserved[1] is for flags */
8004 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8005 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8006#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308007 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8008 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008009#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308010
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008011 /*TODO: Do we need to change it for passthrough */
8012 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008013
Manish Dewangana6fc5442015-08-24 20:30:31 +05308014 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8015 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308016 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308017 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308018 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8019 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308020
8021 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8022 AUDIO_FORMAT_PCM) {
8023
8024 /*Based on platform support, configure appropriate alsa format for corresponding
8025 *hal input format.
8026 */
8027 out->compr_config.codec->format = hal_format_to_alsa(
8028 config->offload_info.format);
8029
Ashish Jain83a6cc22016-06-28 14:34:17 +05308030 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308031 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308032 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308033
Dhananjay Kumarac341582017-02-23 23:42:25 +05308034 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308035 *hal input format and alsa format might differ based on platform support.
8036 */
8037 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308038 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308039
8040 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8041
Deeraj Soman93155a62019-09-30 19:00:37 +05308042 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8043 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8044 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8045 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8046 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308047
Ashish Jainf1eaa582016-05-23 20:54:24 +05308048 /* Check if alsa session is configured with the same format as HAL input format,
8049 * if not then derive correct fragment size needed to accomodate the
8050 * conversion of HAL input format to alsa format.
8051 */
8052 audio_extn_utils_update_direct_pcm_fragment_size(out);
8053
8054 /*if hal input and output fragment size is different this indicates HAL input format is
8055 *not same as the alsa format
8056 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308057 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308058 /*Allocate a buffer to convert input data to the alsa configured format.
8059 *size of convert buffer is equal to the size required to hold one fragment size
8060 *worth of pcm data, this is because flinger does not write more than fragment_size
8061 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308062 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8063 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308064 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8065 ret = -ENOMEM;
8066 goto error_open;
8067 }
8068 }
8069 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8070 out->compr_config.fragment_size =
8071 audio_extn_passthru_get_buffer_size(&config->offload_info);
8072 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8073 } else {
8074 out->compr_config.fragment_size =
8075 platform_get_compress_offload_buffer_size(&config->offload_info);
8076 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8077 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008078
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308079 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8080 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8081 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07008082 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308083 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008084
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308085 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8086 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8087 }
8088
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008089 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8090 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008091
Manish Dewangan69426c82017-01-30 17:35:36 +05308092 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8093 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8094 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8095 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8096 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8097 } else {
8098 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8099 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008100
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308101 memset(&out->channel_map_param, 0,
8102 sizeof(struct audio_out_channel_map_param));
8103
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008104 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308105 out->send_next_track_params = false;
8106 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008107 out->offload_state = OFFLOAD_STATE_IDLE;
8108 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008109 out->writeAt.tv_sec = 0;
8110 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008111
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008112 audio_extn_dts_create_state_notifier_node(out->usecase);
8113
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008114 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8115 __func__, config->offload_info.version,
8116 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308117
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308118 /* Check if DSD audio format is supported in codec
8119 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308120 */
8121
8122 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308123 (!platform_check_codec_dsd_support(adev->platform) ||
8124 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308125 ret = -EINVAL;
8126 goto error_open;
8127 }
8128
Ashish Jain5106d362016-05-11 19:23:33 +05308129 /* Disable gapless if any of the following is true
8130 * passthrough playback
8131 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308132 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308133 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308134 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308135 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008136 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308137 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308138 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308139 check_and_set_gapless_mode(adev, false);
8140 } else
8141 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008142
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308143 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008144 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8145 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308146 if (config->format == AUDIO_FORMAT_DSD) {
8147 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008148#ifdef AUDIO_GKI_ENABLED
8149 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8150 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8151#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308152 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008153#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308154 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008155
8156 create_offload_callback_thread(out);
8157
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008158 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008159 switch (config->sample_rate) {
8160 case 0:
8161 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8162 break;
8163 case 8000:
8164 case 16000:
8165 case 48000:
8166 out->sample_rate = config->sample_rate;
8167 break;
8168 default:
8169 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8170 config->sample_rate);
8171 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8172 ret = -EINVAL;
8173 goto error_open;
8174 }
8175 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8176 switch (config->channel_mask) {
8177 case AUDIO_CHANNEL_NONE:
8178 case AUDIO_CHANNEL_OUT_STEREO:
8179 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8180 break;
8181 default:
8182 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8183 config->channel_mask);
8184 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8185 ret = -EINVAL;
8186 goto error_open;
8187 }
8188 switch (config->format) {
8189 case AUDIO_FORMAT_DEFAULT:
8190 case AUDIO_FORMAT_PCM_16_BIT:
8191 out->format = AUDIO_FORMAT_PCM_16_BIT;
8192 break;
8193 default:
8194 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8195 config->format);
8196 config->format = AUDIO_FORMAT_PCM_16_BIT;
8197 ret = -EINVAL;
8198 goto error_open;
8199 }
8200
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308201 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008202 if (ret != 0) {
8203 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008204 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008205 goto error_open;
8206 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008207 } else if (is_single_device_type_equal(&out->device_list,
8208 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008209 switch (config->sample_rate) {
8210 case 0:
8211 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8212 break;
8213 case 8000:
8214 case 16000:
8215 case 48000:
8216 out->sample_rate = config->sample_rate;
8217 break;
8218 default:
8219 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8220 config->sample_rate);
8221 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8222 ret = -EINVAL;
8223 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008224 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008225 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8226 switch (config->channel_mask) {
8227 case AUDIO_CHANNEL_NONE:
8228 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8229 break;
8230 case AUDIO_CHANNEL_OUT_STEREO:
8231 out->channel_mask = config->channel_mask;
8232 break;
8233 default:
8234 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8235 config->channel_mask);
8236 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8237 ret = -EINVAL;
8238 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008239 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008240 switch (config->format) {
8241 case AUDIO_FORMAT_DEFAULT:
8242 out->format = AUDIO_FORMAT_PCM_16_BIT;
8243 break;
8244 case AUDIO_FORMAT_PCM_16_BIT:
8245 out->format = config->format;
8246 break;
8247 default:
8248 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8249 config->format);
8250 config->format = AUDIO_FORMAT_PCM_16_BIT;
8251 ret = -EINVAL;
8252 break;
8253 }
8254 if (ret != 0)
8255 goto error_open;
8256
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008257 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8258 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008259 out->config.rate = out->sample_rate;
8260 out->config.channels =
8261 audio_channel_count_from_out_mask(out->channel_mask);
8262 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008263 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008264 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308265 unsigned int channels = 0;
8266 /*Update config params to default if not set by the caller*/
8267 if (config->sample_rate == 0)
8268 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8269 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8270 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8271 if (config->format == AUDIO_FORMAT_DEFAULT)
8272 config->format = AUDIO_FORMAT_PCM_16_BIT;
8273
8274 channels = audio_channel_count_from_out_mask(out->channel_mask);
8275
Varun Balaraje49253e2017-07-06 19:48:56 +05308276 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8277 out->usecase = get_interactive_usecase(adev);
8278 out->config = pcm_config_low_latency;
8279 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308280 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008281 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8282 out->flags);
8283 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008284 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8285 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8286 out->config = pcm_config_mmap_playback;
8287 out->stream.start = out_start;
8288 out->stream.stop = out_stop;
8289 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8290 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308291 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8292 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008293 out->hal_output_suspend_supported =
8294 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8295 out->dynamic_pm_qos_config_supported =
8296 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8297 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008298 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8299 } else {
8300 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8301 //the mixer path will be a string similar to "low-latency-playback resume"
8302 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8303 strlcat(out->pm_qos_mixer_path,
8304 " resume", MAX_MIXER_PATH_LEN);
8305 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8306 out->pm_qos_mixer_path);
8307 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308308 out->config = pcm_config_low_latency;
8309 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8310 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8311 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308312 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8313 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8314 if (out->config.period_size <= 0) {
8315 ALOGE("Invalid configuration period size is not valid");
8316 ret = -EINVAL;
8317 goto error_open;
8318 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008319 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8320 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8321 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008322 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8323 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8324 out->config = pcm_config_haptics_audio;
8325 if (force_haptic_path)
8326 adev->haptics_config = pcm_config_haptics_audio;
8327 else
8328 adev->haptics_config = pcm_config_haptics;
8329
Meng Wangd08ce322020-04-02 08:59:20 +08008330 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008331 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8332
8333 if (force_haptic_path) {
8334 out->config.channels = 1;
8335 adev->haptics_config.channels = 1;
8336 } else
8337 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 -08008338 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008339 ret = audio_extn_auto_hal_open_output_stream(out);
8340 if (ret) {
8341 ALOGE("%s: Failed to open output stream for bus device", __func__);
8342 ret = -EINVAL;
8343 goto error_open;
8344 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308345 } else {
8346 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008347 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8348 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308349 }
8350 out->hal_ip_format = format = out->format;
8351 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8352 out->hal_op_format = pcm_format_to_hal(out->config.format);
8353 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8354 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008355 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308356 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308357 if (out->hal_ip_format != out->hal_op_format) {
8358 uint32_t buffer_size = out->config.period_size *
8359 format_to_bitwidth_table[out->hal_op_format] *
8360 out->config.channels;
8361 out->convert_buffer = calloc(1, buffer_size);
8362 if (out->convert_buffer == NULL){
8363 ALOGE("Allocation failed for convert buffer for size %d",
8364 out->compr_config.fragment_size);
8365 ret = -ENOMEM;
8366 goto error_open;
8367 }
8368 ALOGD("Convert buffer allocated of size %d", buffer_size);
8369 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008370 }
8371
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008372 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8373 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308374
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008375 /* TODO remove this hardcoding and check why width is zero*/
8376 if (out->bit_width == 0)
8377 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308378 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008379 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008380 &out->device_list, out->flags,
8381 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308382 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308383 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008384 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008385 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8386 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008387 if(adev->primary_output == NULL)
8388 adev->primary_output = out;
8389 else {
8390 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008391 ret = -EEXIST;
8392 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008393 }
8394 }
8395
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008396 /* Check if this usecase is already existing */
8397 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008398 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8399 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008400 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008401 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008402 ret = -EEXIST;
8403 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008404 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008406 pthread_mutex_unlock(&adev->lock);
8407
8408 out->stream.common.get_sample_rate = out_get_sample_rate;
8409 out->stream.common.set_sample_rate = out_set_sample_rate;
8410 out->stream.common.get_buffer_size = out_get_buffer_size;
8411 out->stream.common.get_channels = out_get_channels;
8412 out->stream.common.get_format = out_get_format;
8413 out->stream.common.set_format = out_set_format;
8414 out->stream.common.standby = out_standby;
8415 out->stream.common.dump = out_dump;
8416 out->stream.common.set_parameters = out_set_parameters;
8417 out->stream.common.get_parameters = out_get_parameters;
8418 out->stream.common.add_audio_effect = out_add_audio_effect;
8419 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8420 out->stream.get_latency = out_get_latency;
8421 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008422#ifdef NO_AUDIO_OUT
8423 out->stream.write = out_write_for_no_output;
8424#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008425 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008426#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008427 out->stream.get_render_position = out_get_render_position;
8428 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008429 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008430
Haynes Mathew George16081042017-05-31 17:16:49 -07008431 if (out->realtime)
8432 out->af_period_multiplier = af_period_multiplier;
8433 else
8434 out->af_period_multiplier = 1;
8435
Andy Hunga1f48fa2019-07-01 18:14:53 -07008436 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008438 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008439 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008440 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008441
8442 config->format = out->stream.common.get_format(&out->stream.common);
8443 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8444 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308445 register_format(out->format, out->supported_formats);
8446 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8447 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008448
Aalique Grahame22e49102018-12-18 14:23:57 -08008449 out->error_log = error_log_create(
8450 ERROR_LOG_ENTRIES,
8451 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8452
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308453 /*
8454 By locking output stream before registering, we allow the callback
8455 to update stream's state only after stream's initial state is set to
8456 adev state.
8457 */
8458 lock_output_stream(out);
8459 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8460 pthread_mutex_lock(&adev->lock);
8461 out->card_status = adev->card_status;
8462 pthread_mutex_unlock(&adev->lock);
8463 pthread_mutex_unlock(&out->lock);
8464
Aalique Grahame22e49102018-12-18 14:23:57 -08008465 stream_app_type_cfg_init(&out->app_type_cfg);
8466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008467 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308468 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008469 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008470
8471 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8472 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8473 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008474 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308475 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008476 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008477 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308478 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8479 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008480 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8481 out->usecase, PCM_PLAYBACK);
8482 hdlr_stream_cfg.flags = out->flags;
8483 hdlr_stream_cfg.type = PCM_PLAYBACK;
8484 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8485 &hdlr_stream_cfg);
8486 if (ret) {
8487 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8488 out->adsp_hdlr_stream_handle = NULL;
8489 }
8490 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308491 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8492 is_direct_passthough, false);
8493 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8494 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008495 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008496 if (ret < 0) {
8497 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8498 out->ip_hdlr_handle = NULL;
8499 }
8500 }
Derek Chenf939fb72018-11-13 13:34:41 -08008501
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008502 ret = io_streams_map_insert(adev, &out->stream.common,
8503 out->handle, AUDIO_PATCH_HANDLE_NONE);
8504 if (ret != 0)
8505 goto error_open;
8506
Derek Chenf939fb72018-11-13 13:34:41 -08008507 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8508 calloc(1, sizeof(streams_output_ctxt_t));
8509 if (out_ctxt == NULL) {
8510 ALOGE("%s fail to allocate output ctxt", __func__);
8511 ret = -ENOMEM;
8512 goto error_open;
8513 }
8514 out_ctxt->output = out;
8515
8516 pthread_mutex_lock(&adev->lock);
8517 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8518 pthread_mutex_unlock(&adev->lock);
8519
Eric Laurent994a6932013-07-17 11:51:42 -07008520 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008521 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008522
8523error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308524 if (out->convert_buffer)
8525 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008526 free(out);
8527 *stream_out = NULL;
8528 ALOGD("%s: exit: ret %d", __func__, ret);
8529 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008530}
8531
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308532void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008533 struct audio_stream_out *stream)
8534{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008535 struct stream_out *out = (struct stream_out *)stream;
8536 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008537 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008538
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008539 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308540
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008541 io_streams_map_remove(adev, out->handle);
8542
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308543 // must deregister from sndmonitor first to prevent races
8544 // between the callback and close_stream
8545 audio_extn_snd_mon_unregister_listener(out);
8546
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008547 /* close adsp hdrl session before standby */
8548 if (out->adsp_hdlr_stream_handle) {
8549 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8550 if (ret)
8551 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8552 out->adsp_hdlr_stream_handle = NULL;
8553 }
8554
Manish Dewangan21a850a2017-08-14 12:03:55 +05308555 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008556 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8557 out->ip_hdlr_handle = NULL;
8558 }
8559
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008560 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308561 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008562 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308563 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308564 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008565 if(ret != 0)
8566 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8567 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008568 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008569 out_standby(&stream->common);
8570
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008571 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008572 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008573 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008574 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008575 if (out->compr_config.codec != NULL)
8576 free(out->compr_config.codec);
8577 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008578
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308579 out->a2dp_compress_mute = false;
8580
Varun Balaraje49253e2017-07-06 19:48:56 +05308581 if (is_interactive_usecase(out->usecase))
8582 free_interactive_usecase(adev, out->usecase);
8583
Ashish Jain83a6cc22016-06-28 14:34:17 +05308584 if (out->convert_buffer != NULL) {
8585 free(out->convert_buffer);
8586 out->convert_buffer = NULL;
8587 }
8588
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008589 if (adev->voice_tx_output == out)
8590 adev->voice_tx_output = NULL;
8591
Aalique Grahame22e49102018-12-18 14:23:57 -08008592 error_log_destroy(out->error_log);
8593 out->error_log = NULL;
8594
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308595 if (adev->primary_output == out)
8596 adev->primary_output = NULL;
8597
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008598 pthread_cond_destroy(&out->cond);
8599 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008600
8601 pthread_mutex_lock(&adev->lock);
8602 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8603 if (out_ctxt != NULL) {
8604 list_remove(&out_ctxt->list);
8605 free(out_ctxt);
8606 } else {
8607 ALOGW("%s, output stream already closed", __func__);
8608 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008609 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008610 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008611 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008612}
8613
8614static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8615{
8616 struct audio_device *adev = (struct audio_device *)dev;
8617 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008618 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008619 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008620 int ret;
8621 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008622 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008623 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008624 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008625
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008626 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008627 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008628
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308629 if (!parms)
8630 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308631
Derek Chen6f293672019-04-01 01:40:24 -07008632 /* notify adev and input/output streams on the snd card status */
8633 adev_snd_mon_cb((void *)adev, parms);
8634
8635 list_for_each(node, &adev->active_outputs_list) {
8636 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8637 streams_output_ctxt_t,
8638 list);
8639 out_snd_mon_cb((void *)out_ctxt->output, parms);
8640 }
8641
8642 list_for_each(node, &adev->active_inputs_list) {
8643 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8644 streams_input_ctxt_t,
8645 list);
8646 in_snd_mon_cb((void *)in_ctxt->input, parms);
8647 }
8648
Zhou Songd6d71752019-05-21 18:08:51 +08008649 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308650 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8651 if (ret >= 0) {
8652 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008653 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308654 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008655 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308656 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008657 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008658 }
8659 }
8660
8661 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8662 if (ret>=0) {
8663 if (!strncmp(value, "false", 5) &&
8664 audio_extn_a2dp_source_is_suspended()) {
8665 struct audio_usecase *usecase;
8666 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008667 list_for_each(node, &adev->usecase_list) {
8668 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008669 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008670 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008671 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008672 reassign_device_list(&usecase->stream.in->device_list,
8673 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008674 select_devices(adev, usecase->id);
8675 }
Zhou Songd6d71752019-05-21 18:08:51 +08008676 }
8677 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308678 }
8679
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008680 status = voice_set_parameters(adev, parms);
8681 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008682 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008683
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008684 status = platform_set_parameters(adev->platform, parms);
8685 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008686 goto done;
8687
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008688 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8689 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008690 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008691 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8692 adev->bluetooth_nrec = true;
8693 else
8694 adev->bluetooth_nrec = false;
8695 }
8696
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008697 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8698 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008699 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8700 adev->screen_off = false;
8701 else
8702 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008703 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008704 }
8705
Eric Laurent4b084132018-10-19 17:33:43 -07008706 ret = str_parms_get_int(parms, "rotation", &val);
8707 if (ret >= 0) {
8708 bool reverse_speakers = false;
8709 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8710 switch (val) {
8711 // FIXME: note that the code below assumes that the speakers are in the correct placement
8712 // relative to the user when the device is rotated 90deg from its default rotation. This
8713 // assumption is device-specific, not platform-specific like this code.
8714 case 270:
8715 reverse_speakers = true;
8716 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8717 break;
8718 case 0:
8719 case 180:
8720 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8721 break;
8722 case 90:
8723 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8724 break;
8725 default:
8726 ALOGE("%s: unexpected rotation of %d", __func__, val);
8727 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008728 }
Eric Laurent4b084132018-10-19 17:33:43 -07008729 if (status == 0) {
8730 // check and set swap
8731 // - check if orientation changed and speaker active
8732 // - set rotation and cache the rotation value
8733 adev->camera_orientation =
8734 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8735 if (!audio_extn_is_maxx_audio_enabled())
8736 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8737 }
8738 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008739
Mingming Yin514a8bc2014-07-29 15:22:21 -07008740 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8741 if (ret >= 0) {
8742 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8743 adev->bt_wb_speech_enabled = true;
8744 else
8745 adev->bt_wb_speech_enabled = false;
8746 }
8747
Zhou Song12c29502019-03-16 10:37:18 +08008748 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8749 if (ret >= 0) {
8750 val = atoi(value);
8751 adev->swb_speech_mode = val;
8752 }
8753
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008754 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8755 if (ret >= 0) {
8756 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308757 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008758 if (audio_is_output_device(val) &&
8759 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008760 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008761 platform_get_controller_stream_from_params(parms, &controller, &stream);
8762 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8763 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008764 if (ret < 0) {
8765 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308766 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008767 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008768 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308769 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008770 /*
8771 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8772 * Per AudioPolicyManager, USB device is higher priority than WFD.
8773 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8774 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8775 * starting voice call on USB
8776 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008777 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308778 if (ret >= 0)
8779 audio_extn_usb_add_device(device, atoi(value));
8780
Zhou Song6f862822017-11-06 17:27:57 +08008781 if (!audio_extn_usb_is_tunnel_supported()) {
8782 ALOGV("detected USB connect .. disable proxy");
8783 adev->allow_afe_proxy_usage = false;
8784 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008785 }
8786 }
8787
8788 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8789 if (ret >= 0) {
8790 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308791 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008792 /*
8793 * The HDMI / Displayport disconnect handling has been moved to
8794 * audio extension to ensure that its parameters are not
8795 * invalidated prior to updating sysfs of the disconnect event
8796 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8797 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308798 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008799 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308800 if (ret >= 0)
8801 audio_extn_usb_remove_device(device, atoi(value));
8802
Zhou Song6f862822017-11-06 17:27:57 +08008803 if (!audio_extn_usb_is_tunnel_supported()) {
8804 ALOGV("detected USB disconnect .. enable proxy");
8805 adev->allow_afe_proxy_usage = true;
8806 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008807 }
8808 }
8809
Aalique Grahame22e49102018-12-18 14:23:57 -08008810 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008811 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008812
8813 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008814 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308815 struct audio_usecase *usecase;
8816 struct listnode *node;
8817 list_for_each(node, &adev->usecase_list) {
8818 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008819 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8820 continue;
8821
8822 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308823 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008824 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308825 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008826 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308827 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308828 ALOGD("Switching to speaker and muting the stream before select_devices");
8829 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308830 //force device switch to re configure encoder
8831 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308832 ALOGD("Unmuting the stream after select_devices");
8833 usecase->stream.out->a2dp_compress_mute = false;
8834 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 +05308835 audio_extn_a2dp_set_handoff_mode(false);
8836 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308837 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308838 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8839 usecase->stream.out->a2dp_compress_mute) {
8840 pthread_mutex_unlock(&adev->lock);
8841 lock_output_stream(usecase->stream.out);
8842 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008843 reassign_device_list(&usecase->stream.out->device_list,
8844 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308845 check_a2dp_restore_l(adev, usecase->stream.out, true);
8846 pthread_mutex_unlock(&usecase->stream.out->lock);
8847 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308848 }
8849 }
8850 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008851
8852 //handle vr audio setparam
8853 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8854 value, sizeof(value));
8855 if (ret >= 0) {
8856 ALOGI("Setting vr mode to be %s", value);
8857 if (!strncmp(value, "true", 4)) {
8858 adev->vr_audio_mode_enabled = true;
8859 ALOGI("Setting vr mode to true");
8860 } else if (!strncmp(value, "false", 5)) {
8861 adev->vr_audio_mode_enabled = false;
8862 ALOGI("Setting vr mode to false");
8863 } else {
8864 ALOGI("wrong vr mode set");
8865 }
8866 }
8867
Eric Laurent4b084132018-10-19 17:33:43 -07008868 //FIXME: to be replaced by proper video capture properties API
8869 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8870 if (ret >= 0) {
8871 int camera_facing = CAMERA_FACING_BACK;
8872 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8873 camera_facing = CAMERA_FACING_FRONT;
8874 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8875 camera_facing = CAMERA_FACING_BACK;
8876 else {
8877 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8878 goto done;
8879 }
8880 adev->camera_orientation =
8881 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8882 struct audio_usecase *usecase;
8883 struct listnode *node;
8884 list_for_each(node, &adev->usecase_list) {
8885 usecase = node_to_item(node, struct audio_usecase, list);
8886 struct stream_in *in = usecase->stream.in;
8887 if (usecase->type == PCM_CAPTURE && in != NULL &&
8888 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8889 select_devices(adev, in->usecase);
8890 }
8891 }
8892 }
8893
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308894 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008895done:
8896 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008897 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308898error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008899 ALOGV("%s: exit with code(%d)", __func__, status);
8900 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008901}
8902
8903static char* adev_get_parameters(const struct audio_hw_device *dev,
8904 const char *keys)
8905{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308906 ALOGD("%s:%s", __func__, keys);
8907
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008908 struct audio_device *adev = (struct audio_device *)dev;
8909 struct str_parms *reply = str_parms_create();
8910 struct str_parms *query = str_parms_create_str(keys);
8911 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308912 char value[256] = {0};
8913 int ret = 0;
8914
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008915 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008916 if (reply) {
8917 str_parms_destroy(reply);
8918 }
8919 if (query) {
8920 str_parms_destroy(query);
8921 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008922 ALOGE("adev_get_parameters: failed to create query or reply");
8923 return NULL;
8924 }
8925
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008926 //handle vr audio getparam
8927
8928 ret = str_parms_get_str(query,
8929 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8930 value, sizeof(value));
8931
8932 if (ret >= 0) {
8933 bool vr_audio_enabled = false;
8934 pthread_mutex_lock(&adev->lock);
8935 vr_audio_enabled = adev->vr_audio_mode_enabled;
8936 pthread_mutex_unlock(&adev->lock);
8937
8938 ALOGI("getting vr mode to %d", vr_audio_enabled);
8939
8940 if (vr_audio_enabled) {
8941 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8942 "true");
8943 goto exit;
8944 } else {
8945 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8946 "false");
8947 goto exit;
8948 }
8949 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008950
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008951 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008952 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008953 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008954 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008955 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08008956 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308957 pthread_mutex_unlock(&adev->lock);
8958
Naresh Tannirud7205b62014-06-20 02:54:48 +05308959exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008960 str = str_parms_to_str(reply);
8961 str_parms_destroy(query);
8962 str_parms_destroy(reply);
8963
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308964 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008965 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008966}
8967
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008968static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008969{
8970 return 0;
8971}
8972
8973static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8974{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008975 int ret;
8976 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008977
8978 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8979
Haynes Mathew George5191a852013-09-11 14:19:36 -07008980 pthread_mutex_lock(&adev->lock);
8981 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008982 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008983 pthread_mutex_unlock(&adev->lock);
8984 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008985}
8986
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008987static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8988 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008989{
8990 return -ENOSYS;
8991}
8992
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008993static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8994 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008995{
8996 return -ENOSYS;
8997}
8998
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008999static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9000 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009001{
9002 return -ENOSYS;
9003}
9004
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009005static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9006 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009007{
9008 return -ENOSYS;
9009}
9010
9011static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9012{
9013 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009014 struct listnode *node;
9015 struct audio_usecase *usecase = NULL;
9016 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009018 pthread_mutex_lock(&adev->lock);
9019 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309020 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9021 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009022 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05309023 if( mode == AUDIO_MODE_CALL_SCREEN ){
9024 adev->current_call_output = adev->primary_output;
9025 voice_start_call(adev);
9026 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009027 (mode == AUDIO_MODE_NORMAL ||
9028 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009029 list_for_each(node, &adev->usecase_list) {
9030 usecase = node_to_item(node, struct audio_usecase, list);
9031 if (usecase->type == VOICE_CALL)
9032 break;
9033 }
9034 if (usecase &&
9035 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9036 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9037 true);
9038 if (ret != 0) {
9039 /* default service interval was successfully updated,
9040 reopen USB backend with new service interval */
9041 check_usecases_codec_backend(adev,
9042 usecase,
9043 usecase->out_snd_device);
9044 }
9045 }
9046
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009047 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009048 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009049 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009050 // restore device for other active usecases after stop call
9051 list_for_each(node, &adev->usecase_list) {
9052 usecase = node_to_item(node, struct audio_usecase, list);
9053 select_devices(adev, usecase->id);
9054 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009055 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009056 }
9057 pthread_mutex_unlock(&adev->lock);
9058 return 0;
9059}
9060
9061static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9062{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009063 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009064 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009065
9066 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009067 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009068 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009069
Derek Chend2530072014-11-24 12:39:14 -08009070 if (adev->ext_hw_plugin)
9071 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009072
9073 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009074 pthread_mutex_unlock(&adev->lock);
9075
9076 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009077}
9078
9079static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9080{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009081 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009082 return 0;
9083}
9084
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009085static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009086 const struct audio_config *config)
9087{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009088 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009089
Aalique Grahame22e49102018-12-18 14:23:57 -08009090 /* Don't know if USB HIFI in this context so use true to be conservative */
9091 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9092 true /*is_usb_hifi */) != 0)
9093 return 0;
9094
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009095 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9096 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009097}
9098
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009099static bool adev_input_allow_hifi_record(struct audio_device *adev,
9100 audio_devices_t devices,
9101 audio_input_flags_t flags,
9102 audio_source_t source) {
9103 const bool allowed = true;
9104
9105 if (!audio_is_usb_in_device(devices))
9106 return !allowed;
9107
9108 switch (flags) {
9109 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009110 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009111 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9112 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009113 default:
9114 return !allowed;
9115 }
9116
9117 switch (source) {
9118 case AUDIO_SOURCE_DEFAULT:
9119 case AUDIO_SOURCE_MIC:
9120 case AUDIO_SOURCE_UNPROCESSED:
9121 break;
9122 default:
9123 return !allowed;
9124 }
9125
9126 switch (adev->mode) {
9127 case 0:
9128 break;
9129 default:
9130 return !allowed;
9131 }
9132
9133 return allowed;
9134}
9135
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009136static int adev_update_voice_comm_input_stream(struct stream_in *in,
9137 struct audio_config *config)
9138{
9139 bool valid_rate = (config->sample_rate == 8000 ||
9140 config->sample_rate == 16000 ||
9141 config->sample_rate == 32000 ||
9142 config->sample_rate == 48000);
9143 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9144
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009145 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009146 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009147 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9148 in->config = default_pcm_config_voip_copp;
9149 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9150 DEFAULT_VOIP_BUF_DURATION_MS,
9151 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009152 } else {
9153 ALOGW("%s No valid input in voip, use defaults"
9154 "sample rate %u, channel mask 0x%X",
9155 __func__, config->sample_rate, in->channel_mask);
9156 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009157 in->config.rate = config->sample_rate;
9158 in->sample_rate = config->sample_rate;
9159 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009160 //XXX needed for voice_extn_compress_voip_open_input_stream
9161 in->config.rate = config->sample_rate;
9162 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309163 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009164 voice_extn_compress_voip_is_active(in->dev)) &&
9165 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9166 valid_rate && valid_ch) {
9167 voice_extn_compress_voip_open_input_stream(in);
9168 // update rate entries to match config from AF
9169 in->config.rate = config->sample_rate;
9170 in->sample_rate = config->sample_rate;
9171 } else {
9172 ALOGW("%s compress voip not active, use defaults", __func__);
9173 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009174 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009175 return 0;
9176}
9177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009178static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009179 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009180 audio_devices_t devices,
9181 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009182 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309183 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009184 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009185 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009186{
9187 struct audio_device *adev = (struct audio_device *)dev;
9188 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009189 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009190 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009191 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309192 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009193 bool is_usb_dev = audio_is_usb_in_device(devices);
9194 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9195 devices,
9196 flags,
9197 source);
Andy Hung94320602018-10-29 18:31:12 -07009198 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9199 " sample_rate %u, channel_mask %#x, format %#x",
9200 __func__, flags, is_usb_dev, may_use_hifi_record,
9201 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309202
kunleizdff872d2018-08-20 14:40:33 +08009203 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009204 is_usb_dev = false;
9205 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9206 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9207 __func__, devices);
9208 }
9209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009210 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009211
9212 if (!(is_usb_dev && may_use_hifi_record)) {
9213 if (config->sample_rate == 0)
9214 config->sample_rate = 48000;
9215 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9216 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9217 if (config->format == AUDIO_FORMAT_DEFAULT)
9218 config->format = AUDIO_FORMAT_PCM_16_BIT;
9219
9220 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9221
Aalique Grahame22e49102018-12-18 14:23:57 -08009222 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9223 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009224 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009226
Rahul Sharma99770982019-03-06 17:05:26 +05309227 pthread_mutex_lock(&adev->lock);
9228 if (in_get_stream(adev, handle) != NULL) {
9229 ALOGW("%s, input stream already opened", __func__);
9230 ret = -EEXIST;
9231 }
9232 pthread_mutex_unlock(&adev->lock);
9233 if (ret)
9234 return ret;
9235
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009236 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009237
9238 if (!in) {
9239 ALOGE("failed to allocate input stream");
9240 return -ENOMEM;
9241 }
9242
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309243 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309244 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9245 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009246 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009247 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009249 in->stream.common.get_sample_rate = in_get_sample_rate;
9250 in->stream.common.set_sample_rate = in_set_sample_rate;
9251 in->stream.common.get_buffer_size = in_get_buffer_size;
9252 in->stream.common.get_channels = in_get_channels;
9253 in->stream.common.get_format = in_get_format;
9254 in->stream.common.set_format = in_set_format;
9255 in->stream.common.standby = in_standby;
9256 in->stream.common.dump = in_dump;
9257 in->stream.common.set_parameters = in_set_parameters;
9258 in->stream.common.get_parameters = in_get_parameters;
9259 in->stream.common.add_audio_effect = in_add_audio_effect;
9260 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9261 in->stream.set_gain = in_set_gain;
9262 in->stream.read = in_read;
9263 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009264 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309265 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009266 in->stream.set_microphone_direction = in_set_microphone_direction;
9267 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009268 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009269
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009270 list_init(&in->device_list);
9271 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009272 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009273 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009274 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009275 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009276 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009277 in->bit_width = 16;
9278 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009279 in->direction = MIC_DIRECTION_UNSPECIFIED;
9280 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009281 list_init(&in->aec_list);
9282 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009283 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009284
Andy Hung94320602018-10-29 18:31:12 -07009285 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009286 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9287 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9288 /* Force channel config requested to mono if incall
9289 record is being requested for only uplink/downlink */
9290 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9291 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9292 ret = -EINVAL;
9293 goto err_open;
9294 }
9295 }
9296
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009297 if (is_usb_dev && may_use_hifi_record) {
9298 /* HiFi record selects an appropriate format, channel, rate combo
9299 depending on sink capabilities*/
9300 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9301 &config->format,
9302 &in->supported_formats[0],
9303 MAX_SUPPORTED_FORMATS,
9304 &config->channel_mask,
9305 &in->supported_channel_masks[0],
9306 MAX_SUPPORTED_CHANNEL_MASKS,
9307 &config->sample_rate,
9308 &in->supported_sample_rates[0],
9309 MAX_SUPPORTED_SAMPLE_RATES);
9310 if (ret != 0) {
9311 ret = -EINVAL;
9312 goto err_open;
9313 }
9314 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009315 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309316 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309317 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9318 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9319 in->config.format = PCM_FORMAT_S32_LE;
9320 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309321 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9322 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9323 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9324 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9325 bool ret_error = false;
9326 in->bit_width = 24;
9327 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9328 from HAL is 24_packed and 8_24
9329 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9330 24_packed return error indicating supported format is 24_packed
9331 *> In case of any other source requesting 24 bit or float return error
9332 indicating format supported is 16 bit only.
9333
9334 on error flinger will retry with supported format passed
9335 */
9336 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9337 (source != AUDIO_SOURCE_CAMCORDER)) {
9338 config->format = AUDIO_FORMAT_PCM_16_BIT;
9339 if (config->sample_rate > 48000)
9340 config->sample_rate = 48000;
9341 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009342 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9343 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309344 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9345 ret_error = true;
9346 }
9347
9348 if (ret_error) {
9349 ret = -EINVAL;
9350 goto err_open;
9351 }
9352 }
9353
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009354 in->channel_mask = config->channel_mask;
9355 in->format = config->format;
9356
9357 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309358
9359 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9360 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9361 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9362 else {
9363 ret = -EINVAL;
9364 goto err_open;
9365 }
9366 }
9367
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009368 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309369 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9370 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009371 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9372 is_low_latency = true;
9373#if LOW_LATENCY_CAPTURE_USE_CASE
9374 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9375#endif
9376 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009377 if (!in->realtime) {
9378 in->config = pcm_config_audio_capture;
9379 frame_size = audio_stream_in_frame_size(&in->stream);
9380 buffer_size = get_input_buffer_size(config->sample_rate,
9381 config->format,
9382 channel_count,
9383 is_low_latency);
9384 in->config.period_size = buffer_size / frame_size;
9385 in->config.rate = config->sample_rate;
9386 in->af_period_multiplier = 1;
9387 } else {
9388 // period size is left untouched for rt mode playback
9389 in->config = pcm_config_audio_capture_rt;
9390 in->af_period_multiplier = af_period_multiplier;
9391 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009392 }
9393
9394 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9395 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9396 in->realtime = 0;
9397 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9398 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009399 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009400 in->stream.start = in_start;
9401 in->stream.stop = in_stop;
9402 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9403 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009404 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009405 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009406 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9407 in->config = pcm_config_audio_capture;
9408 frame_size = audio_stream_in_frame_size(&in->stream);
9409 buffer_size = get_input_buffer_size(config->sample_rate,
9410 config->format,
9411 channel_count,
9412 false /*is_low_latency*/);
9413 in->config.period_size = buffer_size / frame_size;
9414 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009415 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009416 switch (config->format) {
9417 case AUDIO_FORMAT_PCM_32_BIT:
9418 in->bit_width = 32;
9419 break;
9420 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9421 case AUDIO_FORMAT_PCM_8_24_BIT:
9422 in->bit_width = 24;
9423 break;
9424 default:
9425 in->bit_width = 16;
9426 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009427 } else if (is_single_device_type_equal(&in->device_list,
9428 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9429 is_single_device_type_equal(&in->device_list,
9430 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009431 if (config->sample_rate == 0)
9432 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9433 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9434 config->sample_rate != 8000) {
9435 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9436 ret = -EINVAL;
9437 goto err_open;
9438 }
9439 if (config->format == AUDIO_FORMAT_DEFAULT)
9440 config->format = AUDIO_FORMAT_PCM_16_BIT;
9441 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9442 config->format = AUDIO_FORMAT_PCM_16_BIT;
9443 ret = -EINVAL;
9444 goto err_open;
9445 }
9446
9447 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009448 if (adev->ha_proxy_enable &&
9449 is_single_device_type_equal(&in->device_list,
9450 AUDIO_DEVICE_IN_TELEPHONY_RX))
9451 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009452 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009453 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009454 in->af_period_multiplier = 1;
9455 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9456 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9457 (config->sample_rate == 8000 ||
9458 config->sample_rate == 16000 ||
9459 config->sample_rate == 32000 ||
9460 config->sample_rate == 48000) &&
9461 channel_count == 1) {
9462 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9463 in->config = pcm_config_audio_capture;
9464 frame_size = audio_stream_in_frame_size(&in->stream);
9465 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9466 config->sample_rate,
9467 config->format,
9468 channel_count, false /*is_low_latency*/);
9469 in->config.period_size = buffer_size / frame_size;
9470 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9471 in->config.rate = config->sample_rate;
9472 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009473 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309474 int ret_val;
9475 pthread_mutex_lock(&adev->lock);
9476 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9477 in, config, &channel_mask_updated);
9478 pthread_mutex_unlock(&adev->lock);
9479
9480 if (!ret_val) {
9481 if (channel_mask_updated == true) {
9482 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9483 __func__, config->channel_mask);
9484 ret = -EINVAL;
9485 goto err_open;
9486 }
9487 ALOGD("%s: created multi-channel session succesfully",__func__);
9488 } else if (audio_extn_compr_cap_enabled() &&
9489 audio_extn_compr_cap_format_supported(config->format) &&
9490 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9491 audio_extn_compr_cap_init(in);
9492 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309493 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309494 if (ret)
9495 goto err_open;
9496 } else {
9497 in->config = pcm_config_audio_capture;
9498 in->config.rate = config->sample_rate;
9499 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309500 in->format = config->format;
9501 frame_size = audio_stream_in_frame_size(&in->stream);
9502 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009503 config->format,
9504 channel_count,
9505 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009506 /* prevent division-by-zero */
9507 if (frame_size == 0) {
9508 ALOGE("%s: Error frame_size==0", __func__);
9509 ret = -EINVAL;
9510 goto err_open;
9511 }
9512
Revathi Uddarajud2634032017-12-07 14:42:34 +05309513 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009514 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009515
Revathi Uddarajud2634032017-12-07 14:42:34 +05309516 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9517 /* optionally use VOIP usecase depending on config(s) */
9518 ret = adev_update_voice_comm_input_stream(in, config);
9519 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009520
Revathi Uddarajud2634032017-12-07 14:42:34 +05309521 if (ret) {
9522 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9523 goto err_open;
9524 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009525 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309526
9527 /* assign concurrent capture usecase if record has to caried out from
9528 * actual hardware input source */
9529 if (audio_extn_is_concurrent_capture_enabled() &&
9530 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309531 /* Acquire lock to avoid two concurrent use cases initialized to
9532 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009533
Samyak Jainc37062f2019-04-25 18:41:06 +05309534 if (in->usecase == USECASE_AUDIO_RECORD) {
9535 pthread_mutex_lock(&adev->lock);
9536 if (!(adev->pcm_record_uc_state)) {
9537 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9538 adev->pcm_record_uc_state = 1;
9539 pthread_mutex_unlock(&adev->lock);
9540 } else {
9541 pthread_mutex_unlock(&adev->lock);
9542 /* Assign compress record use case for second record */
9543 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9544 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9545 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9546 if (audio_extn_cin_applicable_stream(in)) {
9547 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309548 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309549 if (ret)
9550 goto err_open;
9551 }
9552 }
9553 }
kunleiz28c73e72019-03-27 17:24:04 +08009554 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009555 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309556 if (audio_extn_ssr_get_stream() != in)
9557 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009558
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009559 in->sample_rate = in->config.rate;
9560
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309561 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9562 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009563 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009564 in->sample_rate, in->bit_width,
9565 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309566 register_format(in->format, in->supported_formats);
9567 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9568 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309569
Aalique Grahame22e49102018-12-18 14:23:57 -08009570 in->error_log = error_log_create(
9571 ERROR_LOG_ENTRIES,
9572 1000000000 /* aggregate consecutive identical errors within one second */);
9573
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009574 /* This stream could be for sound trigger lab,
9575 get sound trigger pcm if present */
9576 audio_extn_sound_trigger_check_and_get_session(in);
9577
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309578 lock_input_stream(in);
9579 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9580 pthread_mutex_lock(&adev->lock);
9581 in->card_status = adev->card_status;
9582 pthread_mutex_unlock(&adev->lock);
9583 pthread_mutex_unlock(&in->lock);
9584
Aalique Grahame22e49102018-12-18 14:23:57 -08009585 stream_app_type_cfg_init(&in->app_type_cfg);
9586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009587 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009588
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009589 ret = io_streams_map_insert(adev, &in->stream.common,
9590 handle, AUDIO_PATCH_HANDLE_NONE);
9591 if (ret != 0)
9592 goto err_open;
9593
Derek Chenf939fb72018-11-13 13:34:41 -08009594 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9595 calloc(1, sizeof(streams_input_ctxt_t));
9596 if (in_ctxt == NULL) {
9597 ALOGE("%s fail to allocate input ctxt", __func__);
9598 ret = -ENOMEM;
9599 goto err_open;
9600 }
9601 in_ctxt->input = in;
9602
9603 pthread_mutex_lock(&adev->lock);
9604 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9605 pthread_mutex_unlock(&adev->lock);
9606
Eric Laurent994a6932013-07-17 11:51:42 -07009607 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009608 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009609
9610err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309611 if (in->usecase == USECASE_AUDIO_RECORD) {
9612 pthread_mutex_lock(&adev->lock);
9613 adev->pcm_record_uc_state = 0;
9614 pthread_mutex_unlock(&adev->lock);
9615 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009616 free(in);
9617 *stream_in = NULL;
9618 return ret;
9619}
9620
9621static void adev_close_input_stream(struct audio_hw_device *dev,
9622 struct audio_stream_in *stream)
9623{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009624 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009625 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009626 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309627
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309628 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009629
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009630 if (in == NULL) {
9631 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9632 return;
9633 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009634 io_streams_map_remove(adev, in->capture_handle);
9635
kunleiz70e57612018-12-28 17:50:23 +08009636 /* must deregister from sndmonitor first to prevent races
9637 * between the callback and close_stream
9638 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309639 audio_extn_snd_mon_unregister_listener(stream);
9640
kunleiz70e57612018-12-28 17:50:23 +08009641 /* Disable echo reference if there are no active input, hfp call
9642 * and sound trigger while closing input stream
9643 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009644 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009645 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009646 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9647 struct listnode out_devices;
9648 list_init(&out_devices);
9649 platform_set_echo_reference(adev, false, &out_devices);
9650 } else
kunleiz70e57612018-12-28 17:50:23 +08009651 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309652
Weiyin Jiang2995f662019-04-17 14:25:12 +08009653 error_log_destroy(in->error_log);
9654 in->error_log = NULL;
9655
Pallavid7c7a272018-01-16 11:22:55 +05309656
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009657 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309658 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009659 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309660 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009661 if (ret != 0)
9662 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9663 __func__, ret);
9664 } else
9665 in_standby(&stream->common);
9666
Revathi Uddarajud2634032017-12-07 14:42:34 +05309667 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309668 if (in->usecase == USECASE_AUDIO_RECORD) {
9669 adev->pcm_record_uc_state = 0;
9670 }
9671
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009672 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9673 adev->enable_voicerx = false;
9674 }
9675
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009676 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009677 audio_extn_ssr_deinit();
9678 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009679
Garmond Leunge2433c32017-09-28 21:51:22 -07009680 if (audio_extn_ffv_get_stream() == in) {
9681 audio_extn_ffv_stream_deinit();
9682 }
9683
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309684 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009685 audio_extn_compr_cap_format_supported(in->config.format))
9686 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309687
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309688 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309689 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009690
Mingming Yinfd7607b2016-01-22 12:48:44 -08009691 if (in->is_st_session) {
9692 ALOGV("%s: sound trigger pcm stop lab", __func__);
9693 audio_extn_sound_trigger_stop_lab(in);
9694 }
Derek Chenf939fb72018-11-13 13:34:41 -08009695 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9696 if (in_ctxt != NULL) {
9697 list_remove(&in_ctxt->list);
9698 free(in_ctxt);
9699 } else {
9700 ALOGW("%s, input stream already closed", __func__);
9701 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009702 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309703 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009704 return;
9705}
9706
Aalique Grahame22e49102018-12-18 14:23:57 -08009707/* verifies input and output devices and their capabilities.
9708 *
9709 * This verification is required when enabling extended bit-depth or
9710 * sampling rates, as not all qcom products support it.
9711 *
9712 * Suitable for calling only on initialization such as adev_open().
9713 * It fills the audio_device use_case_table[] array.
9714 *
9715 * Has a side-effect that it needs to configure audio routing / devices
9716 * in order to power up the devices and read the device parameters.
9717 * It does not acquire any hw device lock. Should restore the devices
9718 * back to "normal state" upon completion.
9719 */
9720static int adev_verify_devices(struct audio_device *adev)
9721{
9722 /* enumeration is a bit difficult because one really wants to pull
9723 * the use_case, device id, etc from the hidden pcm_device_table[].
9724 * In this case there are the following use cases and device ids.
9725 *
9726 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9727 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9728 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9729 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9730 * [USECASE_AUDIO_RECORD] = {0, 0},
9731 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9732 * [USECASE_VOICE_CALL] = {2, 2},
9733 *
9734 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9735 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9736 */
9737
9738 /* should be the usecases enabled in adev_open_input_stream() */
9739 static const int test_in_usecases[] = {
9740 USECASE_AUDIO_RECORD,
9741 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9742 };
9743 /* should be the usecases enabled in adev_open_output_stream()*/
9744 static const int test_out_usecases[] = {
9745 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9746 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9747 };
9748 static const usecase_type_t usecase_type_by_dir[] = {
9749 PCM_PLAYBACK,
9750 PCM_CAPTURE,
9751 };
9752 static const unsigned flags_by_dir[] = {
9753 PCM_OUT,
9754 PCM_IN,
9755 };
9756
9757 size_t i;
9758 unsigned dir;
9759 const unsigned card_id = adev->snd_card;
9760
9761 for (dir = 0; dir < 2; ++dir) {
9762 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9763 const unsigned flags_dir = flags_by_dir[dir];
9764 const size_t testsize =
9765 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9766 const int *testcases =
9767 dir ? test_in_usecases : test_out_usecases;
9768 const audio_devices_t audio_device =
9769 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9770
9771 for (i = 0; i < testsize; ++i) {
9772 const audio_usecase_t audio_usecase = testcases[i];
9773 int device_id;
9774 struct pcm_params **pparams;
9775 struct stream_out out;
9776 struct stream_in in;
9777 struct audio_usecase uc_info;
9778 int retval;
9779
9780 pparams = &adev->use_case_table[audio_usecase];
9781 pcm_params_free(*pparams); /* can accept null input */
9782 *pparams = NULL;
9783
9784 /* find the device ID for the use case (signed, for error) */
9785 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9786 if (device_id < 0)
9787 continue;
9788
9789 /* prepare structures for device probing */
9790 memset(&uc_info, 0, sizeof(uc_info));
9791 uc_info.id = audio_usecase;
9792 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009793 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009794 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009795 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009796 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009797 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009798 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9799 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009800 }
9801 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009802 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009803 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009804 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009805 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009806 uc_info.in_snd_device = SND_DEVICE_NONE;
9807 uc_info.out_snd_device = SND_DEVICE_NONE;
9808 list_add_tail(&adev->usecase_list, &uc_info.list);
9809
9810 /* select device - similar to start_(in/out)put_stream() */
9811 retval = select_devices(adev, audio_usecase);
9812 if (retval >= 0) {
9813 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9814#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009815 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009816 if (*pparams) {
9817 ALOGV("%s: (%s) card %d device %d", __func__,
9818 dir ? "input" : "output", card_id, device_id);
9819 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9820 } else {
9821 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9822 }
9823#endif
9824 }
9825
9826 /* deselect device - similar to stop_(in/out)put_stream() */
9827 /* 1. Get and set stream specific mixer controls */
9828 retval = disable_audio_route(adev, &uc_info);
9829 /* 2. Disable the rx device */
9830 retval = disable_snd_device(adev,
9831 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9832 list_remove(&uc_info.list);
9833 }
9834 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009835 return 0;
9836}
9837
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009838int update_patch(unsigned int num_sources,
9839 const struct audio_port_config *sources,
9840 unsigned int num_sinks,
9841 const struct audio_port_config *sinks,
9842 audio_patch_handle_t handle,
9843 struct audio_patch_info *p_info,
9844 patch_type_t patch_type, bool new_patch)
9845{
9846 ALOGD("%s: enter", __func__);
9847
9848 if (p_info == NULL) {
9849 ALOGE("%s: Invalid patch pointer", __func__);
9850 return -EINVAL;
9851 }
9852
9853 if (new_patch) {
9854 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9855 if (p_info->patch == NULL) {
9856 ALOGE("%s: Could not allocate patch", __func__);
9857 return -ENOMEM;
9858 }
9859 }
9860
9861 p_info->patch->id = handle;
9862 p_info->patch->num_sources = num_sources;
9863 p_info->patch->num_sinks = num_sinks;
9864
9865 for (int i = 0; i < num_sources; i++)
9866 p_info->patch->sources[i] = sources[i];
9867 for (int i = 0; i < num_sinks; i++)
9868 p_info->patch->sinks[i] = sinks[i];
9869
9870 p_info->patch_type = patch_type;
9871 return 0;
9872}
9873
9874audio_patch_handle_t generate_patch_handle()
9875{
9876 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9877 if (++patch_handle < 0)
9878 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9879 return patch_handle;
9880}
9881
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309882int adev_create_audio_patch(struct audio_hw_device *dev,
9883 unsigned int num_sources,
9884 const struct audio_port_config *sources,
9885 unsigned int num_sinks,
9886 const struct audio_port_config *sinks,
9887 audio_patch_handle_t *handle)
9888{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009889 int ret = 0;
9890 struct audio_device *adev = (struct audio_device *)dev;
9891 struct audio_patch_info *p_info = NULL;
9892 patch_type_t patch_type = PATCH_NONE;
9893 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9894 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9895 struct audio_stream_info *s_info = NULL;
9896 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009897 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009898 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9899 bool new_patch = false;
9900 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309901
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009902 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9903 num_sources, num_sinks, *handle);
9904
9905 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9906 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9907 ALOGE("%s: Invalid patch arguments", __func__);
9908 ret = -EINVAL;
9909 goto done;
9910 }
9911
9912 if (num_sources > 1) {
9913 ALOGE("%s: Multiple sources are not supported", __func__);
9914 ret = -EINVAL;
9915 goto done;
9916 }
9917
9918 if (sources == NULL || sinks == NULL) {
9919 ALOGE("%s: Invalid sources or sinks port config", __func__);
9920 ret = -EINVAL;
9921 goto done;
9922 }
9923
9924 ALOGV("%s: source role %d, source type %d", __func__,
9925 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009926 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009927
9928 // Populate source/sink information and fetch stream info
9929 switch (sources[0].type) {
9930 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9931 device_type = sources[0].ext.device.type;
9932 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009933 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009934 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9935 patch_type = PATCH_CAPTURE;
9936 io_handle = sinks[0].ext.mix.handle;
9937 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009938 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009939 __func__, device_type, io_handle);
9940 } else {
9941 // Device to device patch is not implemented.
9942 // This space will need changes if audio HAL
9943 // handles device to device patches in the future.
9944 patch_type = PATCH_DEVICE_LOOPBACK;
9945 }
9946 break;
9947 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9948 io_handle = sources[0].ext.mix.handle;
9949 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009950 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009951 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009952 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009953 }
9954 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009955 ALOGD("%s: Playback patch from mix handle %d to device %x",
9956 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009957 break;
9958 case AUDIO_PORT_TYPE_SESSION:
9959 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009960 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9961 ret = -EINVAL;
9962 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009963 }
9964
9965 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009966
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009967 // Generate patch info and update patch
9968 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009969 *handle = generate_patch_handle();
9970 p_info = (struct audio_patch_info *)
9971 calloc(1, sizeof(struct audio_patch_info));
9972 if (p_info == NULL) {
9973 ALOGE("%s: Failed to allocate memory", __func__);
9974 pthread_mutex_unlock(&adev->lock);
9975 ret = -ENOMEM;
9976 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009977 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009978 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009979 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009980 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009981 if (p_info == NULL) {
9982 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9983 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009984 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009985 ret = -EINVAL;
9986 goto done;
9987 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009988 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009989 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009990 *handle, p_info, patch_type, new_patch);
9991
9992 // Fetch stream info of associated mix for playback or capture patches
9993 if (p_info->patch_type == PATCH_PLAYBACK ||
9994 p_info->patch_type == PATCH_CAPTURE) {
9995 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9996 if (s_info == NULL) {
9997 ALOGE("%s: Failed to obtain stream info", __func__);
9998 if (new_patch)
9999 free(p_info);
10000 pthread_mutex_unlock(&adev->lock);
10001 ret = -EINVAL;
10002 goto done;
10003 }
10004 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10005 s_info->patch_handle = *handle;
10006 stream = s_info->stream;
10007 }
10008 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010009
10010 // Update routing for stream
10011 if (stream != NULL) {
10012 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010013 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010014 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010015 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010016 if (ret < 0) {
10017 pthread_mutex_lock(&adev->lock);
10018 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10019 if (new_patch)
10020 free(p_info);
10021 pthread_mutex_unlock(&adev->lock);
10022 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10023 goto done;
10024 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010025 }
10026
10027 // Add new patch to patch map
10028 if (!ret && new_patch) {
10029 pthread_mutex_lock(&adev->lock);
10030 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010031 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010032 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010033 }
10034
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010035done:
10036 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010037 num_sources,
10038 sources,
10039 num_sinks,
10040 sinks,
10041 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010042 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010043 num_sources,
10044 sources,
10045 num_sinks,
10046 sinks,
10047 handle);
10048 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010049}
10050
10051int adev_release_audio_patch(struct audio_hw_device *dev,
10052 audio_patch_handle_t handle)
10053{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010054 struct audio_device *adev = (struct audio_device *) dev;
10055 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010056 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010057 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010058
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010059 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10060 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10061 ret = -EINVAL;
10062 goto done;
10063 }
10064
10065 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010066 pthread_mutex_lock(&adev->lock);
10067 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010068 if (p_info == NULL) {
10069 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010070 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010071 ret = -EINVAL;
10072 goto done;
10073 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010074 struct audio_patch *patch = p_info->patch;
10075 if (patch == NULL) {
10076 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010077 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010078 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010079 goto done;
10080 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010081 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10082 switch (patch->sources[0].type) {
10083 case AUDIO_PORT_TYPE_MIX:
10084 io_handle = patch->sources[0].ext.mix.handle;
10085 break;
10086 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010087 if (p_info->patch_type == PATCH_CAPTURE)
10088 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010089 break;
10090 case AUDIO_PORT_TYPE_SESSION:
10091 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010092 pthread_mutex_unlock(&adev->lock);
10093 ret = -EINVAL;
10094 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010095 }
10096
10097 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010098 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010099 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010100 if (patch_type == PATCH_PLAYBACK ||
10101 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010102 struct audio_stream_info *s_info =
10103 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10104 if (s_info == NULL) {
10105 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10106 pthread_mutex_unlock(&adev->lock);
10107 goto done;
10108 }
10109 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10110 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010111 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010112 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010113
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010114 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010115 struct listnode devices;
10116 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010117 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010118 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010119 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010120 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010121 }
10122
10123 if (ret < 0)
10124 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10125
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010126done:
10127 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10128 audio_extn_auto_hal_release_audio_patch(dev, handle);
10129
10130 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010131 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010132}
10133
10134int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10135{
Derek Chenf13dd492018-11-13 14:53:51 -080010136 int ret = 0;
10137
10138 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10139 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10140 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010141}
10142
10143int adev_set_audio_port_config(struct audio_hw_device *dev,
10144 const struct audio_port_config *config)
10145{
Derek Chenf13dd492018-11-13 14:53:51 -080010146 int ret = 0;
10147
10148 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10149 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10150 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010151}
10152
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010153static int adev_dump(const audio_hw_device_t *device __unused,
10154 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010155{
10156 return 0;
10157}
10158
10159static int adev_close(hw_device_t *device)
10160{
Aalique Grahame22e49102018-12-18 14:23:57 -080010161 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010162 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010163
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010164 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010165 return 0;
10166
10167 pthread_mutex_lock(&adev_init_lock);
10168
10169 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010170 if (audio_extn_spkr_prot_is_enabled())
10171 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010172 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010173 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010174 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010175 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010176 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010177 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010178 audio_extn_utils_release_streams_cfg_lists(
10179 &adev->streams_output_cfg_list,
10180 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010181 if (audio_extn_qap_is_enabled())
10182 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010183 if (audio_extn_qaf_is_enabled())
10184 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010185 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010186 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010187 free(adev->snd_dev_ref_cnt);
10188 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010189 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10190 pcm_params_free(adev->use_case_table[i]);
10191 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010192 if (adev->adm_deinit)
10193 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010194 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010195 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010196 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010197 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010198 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010199 if (adev->device_cfg_params) {
10200 free(adev->device_cfg_params);
10201 adev->device_cfg_params = NULL;
10202 }
Derek Chend2530072014-11-24 12:39:14 -080010203 if(adev->ext_hw_plugin)
10204 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010205 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010206 free_map(adev->patch_map);
10207 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010208 free(device);
10209 adev = NULL;
10210 }
10211 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010212 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010213 return 0;
10214}
10215
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010216/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10217 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10218 * just that it _might_ work.
10219 */
10220static int period_size_is_plausible_for_low_latency(int period_size)
10221{
10222 switch (period_size) {
10223 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010224 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010225 case 240:
10226 case 320:
10227 case 480:
10228 return 1;
10229 default:
10230 return 0;
10231 }
10232}
10233
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010234static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10235{
10236 bool is_snd_card_status = false;
10237 bool is_ext_device_status = false;
10238 char value[32];
10239 int card = -1;
10240 card_status_t status;
10241
10242 if (cookie != adev || !parms)
10243 return;
10244
10245 if (!parse_snd_card_status(parms, &card, &status)) {
10246 is_snd_card_status = true;
10247 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10248 is_ext_device_status = true;
10249 } else {
10250 // not a valid event
10251 return;
10252 }
10253
10254 pthread_mutex_lock(&adev->lock);
10255 if (card == adev->snd_card || is_ext_device_status) {
10256 if (is_snd_card_status && adev->card_status != status) {
10257 adev->card_status = status;
10258 platform_snd_card_update(adev->platform, status);
10259 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010260 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010261 if (status == CARD_STATUS_OFFLINE)
10262 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010263 } else if (is_ext_device_status) {
10264 platform_set_parameters(adev->platform, parms);
10265 }
10266 }
10267 pthread_mutex_unlock(&adev->lock);
10268 return;
10269}
10270
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010271/* out and adev lock held */
10272static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10273{
10274 struct audio_usecase *uc_info;
10275 float left_p;
10276 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010277 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010278
10279 uc_info = get_usecase_from_list(adev, out->usecase);
10280 if (uc_info == NULL) {
10281 ALOGE("%s: Could not find the usecase (%d) in the list",
10282 __func__, out->usecase);
10283 return -EINVAL;
10284 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010285 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010286
10287 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10288 out->usecase, use_case_table[out->usecase]);
10289
10290 if (restore) {
10291 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010292 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010293 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010294 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10295 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010296 pthread_mutex_lock(&out->compr_mute_lock);
10297 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010298 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010299 out->a2dp_compress_mute = false;
10300 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10301 }
10302 pthread_mutex_unlock(&out->compr_mute_lock);
10303 }
10304 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010305 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10306 // mute compress stream if suspended
10307 pthread_mutex_lock(&out->compr_mute_lock);
10308 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010309 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010310 assign_devices(&devices, &out->device_list);
10311 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010312 left_p = out->volume_l;
10313 right_p = out->volume_r;
10314 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10315 compress_pause(out->compr);
10316 out_set_compr_volume(&out->stream, (float)0, (float)0);
10317 out->a2dp_compress_mute = true;
10318 select_devices(adev, out->usecase);
10319 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10320 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010321 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010322 out->volume_l = left_p;
10323 out->volume_r = right_p;
10324 }
Zhou Songc576a452019-09-09 14:17:40 +080010325 pthread_mutex_unlock(&out->compr_mute_lock);
10326 } else {
10327 // tear down a2dp path for non offloaded streams
10328 if (audio_extn_a2dp_source_is_suspended())
10329 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010330 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010331 }
10332 ALOGV("%s: exit", __func__);
10333 return 0;
10334}
10335
10336int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10337{
10338 int ret = 0;
10339
10340 lock_output_stream(out);
10341 pthread_mutex_lock(&adev->lock);
10342
10343 ret = check_a2dp_restore_l(adev, out, restore);
10344
10345 pthread_mutex_unlock(&adev->lock);
10346 pthread_mutex_unlock(&out->lock);
10347 return ret;
10348}
10349
Haynes Mathew George01156f92018-04-13 15:29:54 -070010350void adev_on_battery_status_changed(bool charging)
10351{
10352 pthread_mutex_lock(&adev->lock);
10353 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10354 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010355 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010356 pthread_mutex_unlock(&adev->lock);
10357}
10358
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010359static int adev_open(const hw_module_t *module, const char *name,
10360 hw_device_t **device)
10361{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010362 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010363 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010364 char mixer_ctl_name[128] = {0};
10365 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010366
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010367 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010368 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10369
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010370 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010371 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010372 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010373 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010374 ALOGD("%s: returning existing instance of adev", __func__);
10375 ALOGD("%s: exit", __func__);
10376 pthread_mutex_unlock(&adev_init_lock);
10377 return 0;
10378 }
10379
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010380 adev = calloc(1, sizeof(struct audio_device));
10381
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010382 if (!adev) {
10383 pthread_mutex_unlock(&adev_init_lock);
10384 return -ENOMEM;
10385 }
10386
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010387 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10388
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010389 // register audio ext hidl at the earliest
10390 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010391#ifdef DYNAMIC_LOG_ENABLED
10392 register_for_dynamic_logging("hal");
10393#endif
10394
Derek Chenf939fb72018-11-13 13:34:41 -080010395 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010396 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010397 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10398 maj_version = atoi(value);
10399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010400 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010401 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010402 adev->device.common.module = (struct hw_module_t *)module;
10403 adev->device.common.close = adev_close;
10404
10405 adev->device.init_check = adev_init_check;
10406 adev->device.set_voice_volume = adev_set_voice_volume;
10407 adev->device.set_master_volume = adev_set_master_volume;
10408 adev->device.get_master_volume = adev_get_master_volume;
10409 adev->device.set_master_mute = adev_set_master_mute;
10410 adev->device.get_master_mute = adev_get_master_mute;
10411 adev->device.set_mode = adev_set_mode;
10412 adev->device.set_mic_mute = adev_set_mic_mute;
10413 adev->device.get_mic_mute = adev_get_mic_mute;
10414 adev->device.set_parameters = adev_set_parameters;
10415 adev->device.get_parameters = adev_get_parameters;
10416 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10417 adev->device.open_output_stream = adev_open_output_stream;
10418 adev->device.close_output_stream = adev_close_output_stream;
10419 adev->device.open_input_stream = adev_open_input_stream;
10420 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010421 adev->device.create_audio_patch = adev_create_audio_patch;
10422 adev->device.release_audio_patch = adev_release_audio_patch;
10423 adev->device.get_audio_port = adev_get_audio_port;
10424 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010425 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010426 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010427
10428 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010429 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010430 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010431 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010432 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010433 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010434 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010435 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010436 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010437 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010438 /* Init audio and voice feature */
10439 audio_extn_feature_init();
10440 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010441 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010442 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010443 list_init(&adev->active_inputs_list);
10444 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010445 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010446 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10447 audio_extn_utils_hash_eq);
10448 if (!adev->io_streams_map) {
10449 ALOGE("%s: Could not create io streams map", __func__);
10450 ret = -ENOMEM;
10451 goto adev_open_err;
10452 }
10453 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10454 audio_extn_utils_hash_eq);
10455 if (!adev->patch_map) {
10456 ALOGE("%s: Could not create audio patch map", __func__);
10457 ret = -ENOMEM;
10458 goto adev_open_err;
10459 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010460 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010461 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010462 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010463 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010464 adev->perf_lock_opts[0] = 0x101;
10465 adev->perf_lock_opts[1] = 0x20E;
10466 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010467 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010468 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010469 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010470 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010471
Zhou Song68ebc352019-12-05 17:11:15 +080010472 audio_extn_perf_lock_init();
10473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010474 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010475 adev->platform = platform_init(adev);
10476 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010477 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010478 ret = -EINVAL;
10479 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010480 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010481
Aalique Grahame22e49102018-12-18 14:23:57 -080010482 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010483 if (audio_extn_qap_is_enabled()) {
10484 ret = audio_extn_qap_init(adev);
10485 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010486 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010487 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010488 }
10489 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10490 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10491 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010492
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010493 if (audio_extn_qaf_is_enabled()) {
10494 ret = audio_extn_qaf_init(adev);
10495 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010496 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010497 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010498 }
10499
10500 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10501 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10502 }
10503
Derek Chenae7b0342019-02-08 15:17:04 -080010504 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010505 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10506
Eric Laurentc4aef752013-09-12 17:45:53 -070010507 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10508 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10509 if (adev->visualizer_lib == NULL) {
10510 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10511 } else {
10512 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10513 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010514 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010515 "visualizer_hal_start_output");
10516 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010517 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010518 "visualizer_hal_stop_output");
10519 }
10520 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010521 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010522 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010523 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010524 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010525 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010526 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010527
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010528 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10529 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10530 if (adev->offload_effects_lib == NULL) {
10531 ALOGE("%s: DLOPEN failed for %s", __func__,
10532 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10533 } else {
10534 ALOGV("%s: DLOPEN successful for %s", __func__,
10535 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10536 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010537 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010538 "offload_effects_bundle_hal_start_output");
10539 adev->offload_effects_stop_output =
10540 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10541 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010542 adev->offload_effects_set_hpx_state =
10543 (int (*)(bool))dlsym(adev->offload_effects_lib,
10544 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010545 adev->offload_effects_get_parameters =
10546 (void (*)(struct str_parms *, struct str_parms *))
10547 dlsym(adev->offload_effects_lib,
10548 "offload_effects_bundle_get_parameters");
10549 adev->offload_effects_set_parameters =
10550 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10551 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010552 }
10553 }
10554
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010555 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10556 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10557 if (adev->adm_lib == NULL) {
10558 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10559 } else {
10560 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10561 adev->adm_init = (adm_init_t)
10562 dlsym(adev->adm_lib, "adm_init");
10563 adev->adm_deinit = (adm_deinit_t)
10564 dlsym(adev->adm_lib, "adm_deinit");
10565 adev->adm_register_input_stream = (adm_register_input_stream_t)
10566 dlsym(adev->adm_lib, "adm_register_input_stream");
10567 adev->adm_register_output_stream = (adm_register_output_stream_t)
10568 dlsym(adev->adm_lib, "adm_register_output_stream");
10569 adev->adm_deregister_stream = (adm_deregister_stream_t)
10570 dlsym(adev->adm_lib, "adm_deregister_stream");
10571 adev->adm_request_focus = (adm_request_focus_t)
10572 dlsym(adev->adm_lib, "adm_request_focus");
10573 adev->adm_abandon_focus = (adm_abandon_focus_t)
10574 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010575 adev->adm_set_config = (adm_set_config_t)
10576 dlsym(adev->adm_lib, "adm_set_config");
10577 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10578 dlsym(adev->adm_lib, "adm_request_focus_v2");
10579 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10580 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10581 adev->adm_on_routing_change = (adm_on_routing_change_t)
10582 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010583 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10584 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010585 }
10586 }
10587
Aalique Grahame22e49102018-12-18 14:23:57 -080010588 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010589 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010590 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010591 //initialize this to false for now,
10592 //this will be set to true through set param
10593 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010594
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010595 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010596 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010597
10598 if (k_enable_extended_precision)
10599 adev_verify_devices(adev);
10600
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010601 adev->dsp_bit_width_enforce_mode =
10602 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010603
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010604 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10605 &adev->streams_output_cfg_list,
10606 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010607
Kiran Kandi910e1862013-10-29 13:29:42 -070010608 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010609
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010610 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010611 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010612 trial = atoi(value);
10613 if (period_size_is_plausible_for_low_latency(trial)) {
10614 pcm_config_low_latency.period_size = trial;
10615 pcm_config_low_latency.start_threshold = trial / 4;
10616 pcm_config_low_latency.avail_min = trial / 4;
10617 configured_low_latency_capture_period_size = trial;
10618 }
10619 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010620 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10621 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010622 trial = atoi(value);
10623 if (period_size_is_plausible_for_low_latency(trial)) {
10624 configured_low_latency_capture_period_size = trial;
10625 }
10626 }
10627
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010628 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10629
Eric Laurent4b084132018-10-19 17:33:43 -070010630 adev->camera_orientation = CAMERA_DEFAULT;
10631
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010632 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010633 af_period_multiplier = atoi(value);
10634 if (af_period_multiplier < 0)
10635 af_period_multiplier = 2;
10636 else if (af_period_multiplier > 4)
10637 af_period_multiplier = 4;
10638
10639 ALOGV("new period_multiplier = %d", af_period_multiplier);
10640 }
10641
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010642 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010643
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010644 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010645 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010646 pthread_mutex_unlock(&adev_init_lock);
10647
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010648 if (adev->adm_init)
10649 adev->adm_data = adev->adm_init();
10650
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010651 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010652 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010653
10654 audio_extn_snd_mon_init();
10655 pthread_mutex_lock(&adev->lock);
10656 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10657 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010658 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10659 /*
10660 * if the battery state callback happens before charging can be queried,
10661 * it will be guarded with the adev->lock held in the cb function and so
10662 * the callback value will reflect the latest state
10663 */
10664 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010665 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010666 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010667 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010668 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010669 /* Allocate memory for Device config params */
10670 adev->device_cfg_params = (struct audio_device_config_param*)
10671 calloc(platform_get_max_codec_backend(),
10672 sizeof(struct audio_device_config_param));
10673 if (adev->device_cfg_params == NULL)
10674 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010675
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010676 /*
10677 * Check if new PSPD matrix mixer control is supported. If not
10678 * supported, then set flag so that old mixer ctrl is sent while
10679 * sending pspd coefficients on older kernel version. Query mixer
10680 * control for default pcm id and channel value one.
10681 */
10682 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10683 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10684
10685 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10686 if (!ctl) {
10687 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10688 __func__, mixer_ctl_name);
10689 adev->use_old_pspd_mix_ctrl = true;
10690 }
10691
Eric Laurent994a6932013-07-17 11:51:42 -070010692 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010693 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010694
10695adev_open_err:
10696 free_map(adev->patch_map);
10697 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010698 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010699 pthread_mutex_destroy(&adev->lock);
10700 free(adev);
10701 adev = NULL;
10702 *device = NULL;
10703 pthread_mutex_unlock(&adev_init_lock);
10704 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010705}
10706
10707static struct hw_module_methods_t hal_module_methods = {
10708 .open = adev_open,
10709};
10710
10711struct audio_module HAL_MODULE_INFO_SYM = {
10712 .common = {
10713 .tag = HARDWARE_MODULE_TAG,
10714 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10715 .hal_api_version = HARDWARE_HAL_API_VERSION,
10716 .id = AUDIO_HARDWARE_MODULE_ID,
10717 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010718 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010719 .methods = &hal_module_methods,
10720 },
10721};