blob: 5f534316c2428b4d3898ddcc920af65eb34789d7 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080081#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080082
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053083#ifdef DYNAMIC_LOG_ENABLED
84#include <log_xml_parser.h>
85#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
86#include <log_utils.h>
87#endif
88
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053090/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
91#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070093#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070094#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053095#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053096#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070097#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070098#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070099
Aalique Grahame22e49102018-12-18 14:23:57 -0800100#define RECORD_GAIN_MIN 0.0f
101#define RECORD_GAIN_MAX 1.0f
102#define RECORD_VOLUME_CTL_MAX 0x2000
103
104/* treat as unsigned Q1.13 */
105#define APP_TYPE_GAIN_DEFAULT 0x2000
106
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700107#define PROXY_OPEN_RETRY_COUNT 100
108#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800109
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800110#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
111 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
112 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
113#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
114 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800115
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700116#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700117#define DEFAULT_VOIP_BUF_DURATION_MS 20
118#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
119#define DEFAULT_VOIP_SAMP_RATE 48000
120
121#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
122
123struct pcm_config default_pcm_config_voip_copp = {
124 .channels = 1,
125 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
126 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
127 .period_count = 2,
128 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800129 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
130 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700131};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700132
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700133#define MIN_CHANNEL_COUNT 1
134#define DEFAULT_CHANNEL_COUNT 2
135#define MAX_HIFI_CHANNEL_COUNT 8
136
Aalique Grahame22e49102018-12-18 14:23:57 -0800137#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
138#define MAX_CHANNEL_COUNT 1
139#else
140#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
141#define XSTR(x) STR(x)
142#define STR(x) #x
143#endif
144
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700145static unsigned int configured_low_latency_capture_period_size =
146 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
147
Haynes Mathew George16081042017-05-31 17:16:49 -0700148#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
149#define MMAP_PERIOD_COUNT_MIN 32
150#define MMAP_PERIOD_COUNT_MAX 512
151#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
152
Aalique Grahame22e49102018-12-18 14:23:57 -0800153/* This constant enables extended precision handling.
154 * TODO The flag is off until more testing is done.
155 */
156static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700157extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800158
Eric Laurentb23d5282013-05-14 15:27:20 -0700159struct pcm_config pcm_config_deep_buffer = {
160 .channels = 2,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
163 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
166 .stop_threshold = INT_MAX,
167 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
168};
169
170struct pcm_config pcm_config_low_latency = {
171 .channels = 2,
172 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
173 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
174 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
175 .format = PCM_FORMAT_S16_LE,
176 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
177 .stop_threshold = INT_MAX,
178 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
179};
180
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800181struct pcm_config pcm_config_haptics_audio = {
182 .channels = 1,
183 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
184 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
185 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
187 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
188 .stop_threshold = INT_MAX,
189 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
190};
191
192struct pcm_config pcm_config_haptics = {
193 .channels = 1,
194 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
195 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
196 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
197 .format = PCM_FORMAT_S16_LE,
198 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
199 .stop_threshold = INT_MAX,
200 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
201};
202
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700203static int af_period_multiplier = 4;
204struct pcm_config pcm_config_rt = {
205 .channels = 2,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = ULL_PERIOD_SIZE, //1 ms
208 .period_count = 512, //=> buffer size is 512ms
209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = ULL_PERIOD_SIZE, //1 ms
215};
216
Eric Laurentb23d5282013-05-14 15:27:20 -0700217struct pcm_config pcm_config_hdmi_multi = {
218 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
219 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
220 .period_size = HDMI_MULTI_PERIOD_SIZE,
221 .period_count = HDMI_MULTI_PERIOD_COUNT,
222 .format = PCM_FORMAT_S16_LE,
223 .start_threshold = 0,
224 .stop_threshold = INT_MAX,
225 .avail_min = 0,
226};
227
Haynes Mathew George16081042017-05-31 17:16:49 -0700228struct pcm_config pcm_config_mmap_playback = {
229 .channels = 2,
230 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
231 .period_size = MMAP_PERIOD_SIZE,
232 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
233 .format = PCM_FORMAT_S16_LE,
234 .start_threshold = MMAP_PERIOD_SIZE*8,
235 .stop_threshold = INT32_MAX,
236 .silence_threshold = 0,
237 .silence_size = 0,
238 .avail_min = MMAP_PERIOD_SIZE, //1 ms
239};
240
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700241struct pcm_config pcm_config_hifi = {
242 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
243 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
244 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
245 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
246 .format = PCM_FORMAT_S24_3LE,
247 .start_threshold = 0,
248 .stop_threshold = INT_MAX,
249 .avail_min = 0,
250};
251
Eric Laurentb23d5282013-05-14 15:27:20 -0700252struct pcm_config pcm_config_audio_capture = {
253 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700254 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
255 .format = PCM_FORMAT_S16_LE,
256};
257
Haynes Mathew George16081042017-05-31 17:16:49 -0700258struct pcm_config pcm_config_mmap_capture = {
259 .channels = 2,
260 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
261 .period_size = MMAP_PERIOD_SIZE,
262 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
263 .format = PCM_FORMAT_S16_LE,
264 .start_threshold = 0,
265 .stop_threshold = INT_MAX,
266 .silence_threshold = 0,
267 .silence_size = 0,
268 .avail_min = MMAP_PERIOD_SIZE, //1 ms
269};
270
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700271#define AFE_PROXY_CHANNEL_COUNT 2
272#define AFE_PROXY_SAMPLING_RATE 48000
273
274#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
275#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
276
277struct pcm_config pcm_config_afe_proxy_playback = {
278 .channels = AFE_PROXY_CHANNEL_COUNT,
279 .rate = AFE_PROXY_SAMPLING_RATE,
280 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
281 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
282 .format = PCM_FORMAT_S16_LE,
283 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
284 .stop_threshold = INT_MAX,
285 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286};
287
288#define AFE_PROXY_RECORD_PERIOD_SIZE 768
289#define AFE_PROXY_RECORD_PERIOD_COUNT 4
290
Aalique Grahame22e49102018-12-18 14:23:57 -0800291struct pcm_config pcm_config_audio_capture_rt = {
292 .channels = 2,
293 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
294 .period_size = ULL_PERIOD_SIZE,
295 .period_count = 512,
296 .format = PCM_FORMAT_S16_LE,
297 .start_threshold = 0,
298 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
299 .silence_threshold = 0,
300 .silence_size = 0,
301 .avail_min = ULL_PERIOD_SIZE, //1 ms
302};
303
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700304struct pcm_config pcm_config_afe_proxy_record = {
305 .channels = AFE_PROXY_CHANNEL_COUNT,
306 .rate = AFE_PROXY_SAMPLING_RATE,
307 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
308 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
309 .format = PCM_FORMAT_S16_LE,
310 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
311 .stop_threshold = INT_MAX,
312 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
313};
314
Ashish Jainf1eaa582016-05-23 20:54:24 +0530315#define AUDIO_MAX_PCM_FORMATS 7
316
317const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
318 [AUDIO_FORMAT_DEFAULT] = 0,
319 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
320 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
321 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
322 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
323 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
324 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
325};
326
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800327const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700328 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
329 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800330 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Meng Wang51d8c2a2020-04-27 15:23:21 +0800331 [USECASE_AUDIO_PLAYBACK_HAPTICS] = "haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700332 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
333 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700334 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700335 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700336 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
341 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
343 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700344 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
345 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700346 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800347 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700348
Eric Laurentb23d5282013-05-14 15:27:20 -0700349 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700350 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530351 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
352 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
353 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530354 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
355 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700356 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700357 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700358 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700359 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700360
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800361 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800362 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400363 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
364 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700365
Derek Chenf7092792017-05-23 12:23:53 -0400366 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700367 [USECASE_VOICE2_CALL] = "voice2-call",
368 [USECASE_VOLTE_CALL] = "volte-call",
369 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800370 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800371 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
372 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800373 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700374 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
375 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
376 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800377 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
378 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
379 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
380
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700381 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
382 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700383 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
384 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700385
386 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
387 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Zhou Song62ea0282020-03-22 19:53:01 +0800388 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530389 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700390
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530391 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530392 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
393 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700394
395 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
396 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530397 /* For Interactive Audio Streams */
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
401 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
402 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
403 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
404 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
405 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700406
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800407 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
408
Derek Chenf6318be2017-06-12 17:16:24 -0400409 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
410
411 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
412 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
413 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
414 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chen1bcdc6b2020-02-06 22:44:53 -0800415 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700416 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530417 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700418};
419
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700420static const audio_usecase_t offload_usecases[] = {
421 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700422 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
426 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
427 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
428 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
429 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700430};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800431
Varun Balaraje49253e2017-07-06 19:48:56 +0530432static const audio_usecase_t interactive_usecases[] = {
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
437 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
438 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
439 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
440 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
441};
442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443#define STRING_TO_ENUM(string) { #string, string }
444
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800445struct string_to_enum {
446 const char *name;
447 uint32_t value;
448};
449
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700450static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700455 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800456 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
457 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800458 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700459 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
460 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
461 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
466 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
467 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
468 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
469 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800470};
471
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700472static const struct string_to_enum formats_name_to_enum_table[] = {
473 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
474 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
475 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700476 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
477 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
478 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700479 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800480 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
481 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700482 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800483};
484
485//list of all supported sample rates by HDMI specification.
486static const int out_hdmi_sample_rates[] = {
487 32000, 44100, 48000, 88200, 96000, 176400, 192000,
488};
489
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700490static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800491 STRING_TO_ENUM(32000),
492 STRING_TO_ENUM(44100),
493 STRING_TO_ENUM(48000),
494 STRING_TO_ENUM(88200),
495 STRING_TO_ENUM(96000),
496 STRING_TO_ENUM(176400),
497 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800498 STRING_TO_ENUM(352800),
499 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700500};
501
Carter Hsu2e429db2019-05-14 18:50:52 +0800502struct in_effect_list {
503 struct listnode list;
504 effect_handle_t handle;
505};
506
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700507static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700508static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700509static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700510//cache last MBDRC cal step level
511static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700512
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530513static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
514static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700515static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800516static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530517static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530518
Derek Chen6f293672019-04-01 01:40:24 -0700519static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
520static void in_snd_mon_cb(void * stream, struct str_parms * parms);
521static void out_snd_mon_cb(void * stream, struct str_parms * parms);
522
Zhou Song331c8e52019-08-26 14:16:12 +0800523static int configure_btsco_sample_rate(snd_device_t snd_device);
524
Vatsal Buchac09ae062018-11-14 13:25:08 +0530525#ifdef AUDIO_FEATURE_ENABLED_GCOV
526extern void __gcov_flush();
527static void enable_gcov()
528{
529 __gcov_flush();
530}
531#else
532static void enable_gcov()
533{
534}
535#endif
536
justinweng20fb6d82019-02-21 18:49:00 -0700537static int in_set_microphone_direction(const struct audio_stream_in *stream,
538 audio_microphone_direction_t dir);
539static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
540
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700541static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
542 int flags __unused)
543{
544 int dir = 0;
545 switch (uc_id) {
546 case USECASE_AUDIO_RECORD_LOW_LATENCY:
547 dir = 1;
548 case USECASE_AUDIO_PLAYBACK_ULL:
549 break;
550 default:
551 return false;
552 }
553
554 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
555 PCM_PLAYBACK : PCM_CAPTURE);
556 if (adev->adm_is_noirq_avail)
557 return adev->adm_is_noirq_avail(adev->adm_data,
558 adev->snd_card, dev_id, dir);
559 return false;
560}
561
562static void register_out_stream(struct stream_out *out)
563{
564 struct audio_device *adev = out->dev;
565 if (is_offload_usecase(out->usecase) ||
566 !adev->adm_register_output_stream)
567 return;
568
569 // register stream first for backward compatibility
570 adev->adm_register_output_stream(adev->adm_data,
571 out->handle,
572 out->flags);
573
574 if (!adev->adm_set_config)
575 return;
576
577 if (out->realtime)
578 adev->adm_set_config(adev->adm_data,
579 out->handle,
580 out->pcm, &out->config);
581}
582
583static void register_in_stream(struct stream_in *in)
584{
585 struct audio_device *adev = in->dev;
586 if (!adev->adm_register_input_stream)
587 return;
588
589 adev->adm_register_input_stream(adev->adm_data,
590 in->capture_handle,
591 in->flags);
592
593 if (!adev->adm_set_config)
594 return;
595
596 if (in->realtime)
597 adev->adm_set_config(adev->adm_data,
598 in->capture_handle,
599 in->pcm,
600 &in->config);
601}
602
603static void request_out_focus(struct stream_out *out, long ns)
604{
605 struct audio_device *adev = out->dev;
606
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700607 if (adev->adm_request_focus_v2)
608 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
609 else if (adev->adm_request_focus)
610 adev->adm_request_focus(adev->adm_data, out->handle);
611}
612
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700613static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700614{
615 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700616 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700617
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700618 if (adev->adm_request_focus_v2_1)
619 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
620 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700621 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
622 else if (adev->adm_request_focus)
623 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700624
625 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700626}
627
628static void release_out_focus(struct stream_out *out)
629{
630 struct audio_device *adev = out->dev;
631
632 if (adev->adm_abandon_focus)
633 adev->adm_abandon_focus(adev->adm_data, out->handle);
634}
635
636static void release_in_focus(struct stream_in *in)
637{
638 struct audio_device *adev = in->dev;
639 if (adev->adm_abandon_focus)
640 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
641}
642
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530643static int parse_snd_card_status(struct str_parms *parms, int *card,
644 card_status_t *status)
645{
646 char value[32]={0};
647 char state[32]={0};
648
649 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
650 if (ret < 0)
651 return -1;
652
653 // sscanf should be okay as value is of max length 32.
654 // same as sizeof state.
655 if (sscanf(value, "%d,%s", card, state) < 2)
656 return -1;
657
658 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
659 CARD_STATUS_OFFLINE;
660 return 0;
661}
662
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700663static inline void adjust_frames_for_device_delay(struct stream_out *out,
664 uint32_t *dsp_frames) {
665 // Adjustment accounts for A2dp encoder latency with offload usecases
666 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800667 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700668 unsigned long offset =
669 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
670 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
671 }
672}
673
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700674static inline bool free_entry(void *key __unused,
675 void *value, void *context __unused)
676{
677 free(value);
678 return true;
679}
680
681static inline void free_map(Hashmap *map)
682{
683 if (map) {
684 hashmapForEach(map, free_entry, (void *) NULL);
685 hashmapFree(map);
686 }
687}
688
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800689static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700690 audio_patch_handle_t patch_handle)
691{
692 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
693 return;
694
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700695 struct audio_patch_info *p_info =
696 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
697 if (p_info) {
698 ALOGV("%s: Remove patch %d", __func__, patch_handle);
699 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
700 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700701 free(p_info);
702 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700703}
704
705static inline int io_streams_map_insert(struct audio_device *adev,
706 struct audio_stream *stream,
707 audio_io_handle_t handle,
708 audio_patch_handle_t patch_handle)
709{
710 struct audio_stream_info *s_info =
711 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
712
713 if (s_info == NULL) {
714 ALOGE("%s: Could not allocate stream info", __func__);
715 return -ENOMEM;
716 }
717 s_info->stream = stream;
718 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700719
720 pthread_mutex_lock(&adev->lock);
721 struct audio_stream_info *stream_info =
722 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700723 if (stream_info != NULL)
724 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800725 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700726 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
727 return 0;
728}
729
730static inline void io_streams_map_remove(struct audio_device *adev,
731 audio_io_handle_t handle)
732{
733 pthread_mutex_lock(&adev->lock);
734 struct audio_stream_info *s_info =
735 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700736 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800737 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700738 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800739 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700740 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800741done:
742 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 return;
744}
745
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800746static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 audio_patch_handle_t handle)
748{
749 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700750 p_info = (struct audio_patch_info *)
751 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700752 return p_info;
753}
754
vivek mehtaa76401a2015-04-24 14:12:15 -0700755__attribute__ ((visibility ("default")))
756bool audio_hw_send_gain_dep_calibration(int level) {
757 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700758 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700759
760 pthread_mutex_lock(&adev_init_lock);
761
762 if (adev != NULL && adev->platform != NULL) {
763 pthread_mutex_lock(&adev->lock);
764 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700765
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530766 // cache level info for any of the use case which
767 // was not started.
768 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700769
vivek mehtaa76401a2015-04-24 14:12:15 -0700770 pthread_mutex_unlock(&adev->lock);
771 } else {
772 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
773 }
774
775 pthread_mutex_unlock(&adev_init_lock);
776
777 return ret_val;
778}
779
Ashish Jain5106d362016-05-11 19:23:33 +0530780static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
781{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800782 bool gapless_enabled = false;
783 const char *mixer_ctl_name = "Compress Gapless Playback";
784 struct mixer_ctl *ctl;
785
786 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700787 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530788
789 /*Disable gapless if its AV playback*/
790 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800791
792 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
793 if (!ctl) {
794 ALOGE("%s: Could not get ctl for mixer cmd - %s",
795 __func__, mixer_ctl_name);
796 return -EINVAL;
797 }
798
799 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
800 ALOGE("%s: Could not set gapless mode %d",
801 __func__, gapless_enabled);
802 return -EINVAL;
803 }
804 return 0;
805}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700806
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700807__attribute__ ((visibility ("default")))
808int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
809 int table_size) {
810 int ret_val = 0;
811 ALOGV("%s: enter ... ", __func__);
812
813 pthread_mutex_lock(&adev_init_lock);
814 if (adev == NULL) {
815 ALOGW("%s: adev is NULL .... ", __func__);
816 goto done;
817 }
818
819 pthread_mutex_lock(&adev->lock);
820 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
821 pthread_mutex_unlock(&adev->lock);
822done:
823 pthread_mutex_unlock(&adev_init_lock);
824 ALOGV("%s: exit ... ", __func__);
825 return ret_val;
826}
827
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800828bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800829{
830 bool ret = false;
831 ALOGV("%s: enter ...", __func__);
832
833 pthread_mutex_lock(&adev_init_lock);
834
835 if (adev != NULL && adev->platform != NULL) {
836 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800837 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800838 pthread_mutex_unlock(&adev->lock);
839 }
840
841 pthread_mutex_unlock(&adev_init_lock);
842
843 ALOGV("%s: exit with ret %d", __func__, ret);
844 return ret;
845}
Aalique Grahame22e49102018-12-18 14:23:57 -0800846
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700847static bool is_supported_format(audio_format_t format)
848{
Eric Laurent86e17132013-09-12 17:49:30 -0700849 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530850 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530851 format == AUDIO_FORMAT_AAC_LC ||
852 format == AUDIO_FORMAT_AAC_HE_V1 ||
853 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530854 format == AUDIO_FORMAT_AAC_ADTS_LC ||
855 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
856 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530857 format == AUDIO_FORMAT_AAC_LATM_LC ||
858 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
859 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530860 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
861 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530862 format == AUDIO_FORMAT_PCM_FLOAT ||
863 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700864 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530865 format == AUDIO_FORMAT_AC3 ||
866 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700867 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530868 format == AUDIO_FORMAT_DTS ||
869 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800870 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530871 format == AUDIO_FORMAT_ALAC ||
872 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530873 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530874 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800875 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530876 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700877 format == AUDIO_FORMAT_APTX ||
878 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800879 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700880
881 return false;
882}
883
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700884static inline bool is_mmap_usecase(audio_usecase_t uc_id)
885{
886 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800887 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700888 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
889}
890
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700891static inline bool is_valid_volume(float left, float right)
892{
893 return ((left >= 0.0f && right >= 0.0f) ? true : false);
894}
895
Avinash Vaish71a8b972014-07-24 15:36:33 +0530896static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
897 struct audio_usecase *uc_info)
898{
899 struct listnode *node;
900 struct audio_usecase *usecase;
901
902 if (uc_info == NULL)
903 return -EINVAL;
904
905 /* Re-route all voice usecases on the shared backend other than the
906 specified usecase to new snd devices */
907 list_for_each(node, &adev->usecase_list) {
908 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800909 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530910 enable_audio_route(adev, usecase);
911 }
912 return 0;
913}
914
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530915static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530916{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530917 ALOGV("%s", __func__);
918 audio_route_apply_and_update_path(adev->audio_route,
919 "asrc-mode");
920 adev->asrc_mode_enabled = true;
921}
922
923static void disable_asrc_mode(struct audio_device *adev)
924{
925 ALOGV("%s", __func__);
926 audio_route_reset_and_update_path(adev->audio_route,
927 "asrc-mode");
928 adev->asrc_mode_enabled = false;
929}
930
931/*
932 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
933 * 44.1 or Native DSD backends are enabled for any of current use case.
934 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
935 * - Disable current mix path use case(Headphone backend) and re-enable it with
936 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
937 * e.g. Naitve DSD or Headphone 44.1 -> + 48
938 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530939static void check_and_set_asrc_mode(struct audio_device *adev,
940 struct audio_usecase *uc_info,
941 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530942{
943 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530944 int i, num_new_devices = 0;
945 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
946 /*
947 *Split snd device for new combo use case
948 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
949 */
950 if (platform_split_snd_device(adev->platform,
951 snd_device,
952 &num_new_devices,
953 split_new_snd_devices) == 0) {
954 for (i = 0; i < num_new_devices; i++)
955 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
956 } else {
957 int new_backend_idx = platform_get_backend_index(snd_device);
958 if (((new_backend_idx == HEADPHONE_BACKEND) ||
959 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
960 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
961 !adev->asrc_mode_enabled) {
962 struct listnode *node = NULL;
963 struct audio_usecase *uc = NULL;
964 struct stream_out *curr_out = NULL;
965 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
966 int i, num_devices, ret = 0;
967 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530968
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530969 list_for_each(node, &adev->usecase_list) {
970 uc = node_to_item(node, struct audio_usecase, list);
971 curr_out = (struct stream_out*) uc->stream.out;
972 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
973 /*
974 *Split snd device for existing combo use case
975 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
976 */
977 ret = platform_split_snd_device(adev->platform,
978 uc->out_snd_device,
979 &num_devices,
980 split_snd_devices);
981 if (ret < 0 || num_devices == 0) {
982 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
983 split_snd_devices[0] = uc->out_snd_device;
984 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800985 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530986 for (i = 0; i < num_devices; i++) {
987 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
988 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
989 if((new_backend_idx == HEADPHONE_BACKEND) &&
990 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
991 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
992 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
993 __func__);
994 enable_asrc_mode(adev);
995 break;
996 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
997 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
998 (usecase_backend_idx == HEADPHONE_BACKEND)) {
999 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
1000 __func__);
1001 disable_audio_route(adev, uc);
1002 disable_snd_device(adev, uc->out_snd_device);
1003 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1004 if (new_backend_idx == DSD_NATIVE_BACKEND)
1005 audio_route_apply_and_update_path(adev->audio_route,
1006 "hph-true-highquality-mode");
1007 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1008 (curr_out->bit_width >= 24))
1009 audio_route_apply_and_update_path(adev->audio_route,
1010 "hph-highquality-mode");
1011 enable_asrc_mode(adev);
1012 enable_snd_device(adev, uc->out_snd_device);
1013 enable_audio_route(adev, uc);
1014 break;
1015 }
1016 }
1017 // reset split devices count
1018 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001019 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301020 if (adev->asrc_mode_enabled)
1021 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301022 }
1023 }
1024 }
1025}
1026
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001027static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1028 struct audio_effect_config effect_config,
1029 unsigned int param_value)
1030{
1031 char mixer_ctl_name[] = "Audio Effect";
1032 struct mixer_ctl *ctl;
1033 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001034 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001035
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001036 if (in == NULL) {
1037 ALOGE("%s: active input stream is NULL", __func__);
1038 return -EINVAL;
1039 }
1040
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001041 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1042 if (!ctl) {
1043 ALOGE("%s: Could not get mixer ctl - %s",
1044 __func__, mixer_ctl_name);
1045 return -EINVAL;
1046 }
1047
1048 set_values[0] = 1; //0:Rx 1:Tx
1049 set_values[1] = in->app_type_cfg.app_type;
1050 set_values[2] = (long)effect_config.module_id;
1051 set_values[3] = (long)effect_config.instance_id;
1052 set_values[4] = (long)effect_config.param_id;
1053 set_values[5] = param_value;
1054
1055 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1056
1057 return 0;
1058
1059}
1060
1061static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1062 int effect_type, unsigned int *param_value)
1063{
1064 int ret = 0;
1065 struct audio_effect_config other_effect_config;
1066 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001067 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001068
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001069 if (in == NULL) {
1070 ALOGE("%s: active input stream is NULL", __func__);
1071 return -EINVAL;
1072 }
1073
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001074 usecase = get_usecase_from_list(adev, in->usecase);
1075 if (!usecase)
1076 return -EINVAL;
1077
1078 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1079 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1080 if (ret < 0) {
1081 ALOGE("%s Failed to get effect params %d", __func__, ret);
1082 return ret;
1083 }
1084
1085 if (module_id == other_effect_config.module_id) {
1086 //Same module id for AEC/NS. Values need to be combined
1087 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1088 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1089 *param_value |= other_effect_config.param_value;
1090 }
1091 }
1092
1093 return ret;
1094}
1095
1096static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301097{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001098 struct audio_effect_config effect_config;
1099 struct audio_usecase *usecase = NULL;
1100 int ret = 0;
1101 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001102 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001103
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001104 if(!voice_extn_is_dynamic_ecns_enabled())
1105 return ENOSYS;
1106
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001107 if (!in) {
1108 ALOGE("%s: Invalid input stream", __func__);
1109 return -EINVAL;
1110 }
1111
1112 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1113
1114 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001115 if (usecase == NULL) {
1116 ALOGE("%s: Could not find the usecase (%d) in the list",
1117 __func__, in->usecase);
1118 return -EINVAL;
1119 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001120
1121 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1122 if (ret < 0) {
1123 ALOGE("%s Failed to get module id %d", __func__, ret);
1124 return ret;
1125 }
1126 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1127 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1128
1129 if(enable)
1130 param_value = effect_config.param_value;
1131
1132 /*Special handling for AEC & NS effects Param values need to be
1133 updated if module ids are same*/
1134
1135 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1136 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1137 if (ret < 0)
1138 return ret;
1139 }
1140
1141 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1142
1143 return ret;
1144}
1145
1146static void check_and_enable_effect(struct audio_device *adev)
1147{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001148 if(!voice_extn_is_dynamic_ecns_enabled())
1149 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001150
Eric Laurent637e2d42018-11-15 12:24:31 -08001151 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001152
Eric Laurent637e2d42018-11-15 12:24:31 -08001153 if (in != NULL && !in->standby) {
1154 if (in->enable_aec)
1155 enable_disable_effect(adev, EFFECT_AEC, true);
1156
1157 if (in->enable_ns &&
1158 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1159 enable_disable_effect(adev, EFFECT_NS, true);
1160 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001161 }
1162}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001163
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001164int pcm_ioctl(struct pcm *pcm, int request, ...)
1165{
1166 va_list ap;
1167 void * arg;
1168 int pcm_fd = *(int*)pcm;
1169
1170 va_start(ap, request);
1171 arg = va_arg(ap, void *);
1172 va_end(ap);
1173
1174 return ioctl(pcm_fd, request, arg);
1175}
1176
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001177int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001178 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001179{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001180 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001181 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301182 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301183 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001184 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301185 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001186
1187 if (usecase == NULL)
1188 return -EINVAL;
1189
1190 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1191
Carter Hsu2e429db2019-05-14 18:50:52 +08001192 if (usecase->type == PCM_CAPTURE) {
1193 struct stream_in *in = usecase->stream.in;
1194 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001195 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001196
1197 if (in) {
1198 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001199 list_init(&out_devices);
1200 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001201 struct listnode *node;
1202 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1203 USECASE_AUDIO_PLAYBACK_VOIP);
1204 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001205 assign_devices(&out_devices,
1206 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001207 } else if (adev->primary_output &&
1208 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001209 assign_devices(&out_devices,
1210 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001211 } else {
1212 list_for_each(node, &adev->usecase_list) {
1213 uinfo = node_to_item(node, struct audio_usecase, list);
1214 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001215 assign_devices(&out_devices,
1216 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001217 break;
1218 }
1219 }
1220 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001221
1222 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001223 in->ec_opened = true;
1224 }
1225 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001226 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1227 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1228 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001229 snd_device = usecase->in_snd_device;
1230 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001231 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001232 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001233
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001234#ifdef DS1_DOLBY_DAP_ENABLED
1235 audio_extn_dolby_set_dmid(adev);
1236 audio_extn_dolby_set_endpoint(adev);
1237#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001238 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001239 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301240 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001241 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001242 if (audio_extn_is_maxx_audio_enabled())
1243 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301244 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301245 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1246 out = usecase->stream.out;
1247 if (out && out->compr)
1248 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1249 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301250
1251 if (usecase->type == PCM_CAPTURE) {
1252 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001253 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301254 ALOGD("%s: set custom mtmx params v1", __func__);
1255 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1256 }
1257 } else {
1258 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1259 }
Manish Dewangan58229382017-02-02 15:48:41 +05301260
Andy Hung756ecc12018-10-19 17:47:12 -07001261 // we shouldn't truncate mixer_path
1262 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1263 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1264 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001265 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001266 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301267 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1268 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1269 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1270 if (parms) {
1271 audio_extn_fm_set_parameters(adev, parms);
1272 str_parms_destroy(parms);
1273 }
1274 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275 ALOGV("%s: exit", __func__);
1276 return 0;
1277}
1278
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001279int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001280 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001282 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001283 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301284 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001285
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301286 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001287 return -EINVAL;
1288
1289 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301290 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001291 snd_device = usecase->in_snd_device;
1292 else
1293 snd_device = usecase->out_snd_device;
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001294
1295 /* disable island and power mode on supported device for voice call */
1296 if (usecase->type == VOICE_CALL) {
1297 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1298 if (platform_get_island_cfg_on_device(adev->platform, usecase->in_snd_device) &&
1299 platform_get_power_mode_on_device(adev->platform, usecase->in_snd_device)) {
1300 platform_set_island_cfg_on_device(adev, usecase->in_snd_device, false);
1301 platform_set_power_mode_on_device(adev, usecase->in_snd_device, false);
1302 platform_reset_island_power_status(adev->platform, usecase->in_snd_device);
1303 ALOGD("%s: disable island cfg and power mode in voice tx path",
1304 __func__);
1305 }
1306 }
1307 if (usecase->out_snd_device != SND_DEVICE_NONE) {
1308 if (platform_get_island_cfg_on_device(adev->platform, usecase->out_snd_device) &&
1309 platform_get_power_mode_on_device(adev->platform, usecase->out_snd_device)) {
1310 platform_set_island_cfg_on_device(adev, usecase->out_snd_device, false);
1311 platform_set_power_mode_on_device(adev, usecase->out_snd_device, false);
1312 platform_reset_island_power_status(adev->platform, usecase->out_snd_device);
1313 ALOGD("%s: disable island cfg and power mode in voice rx path",
1314 __func__);
1315 }
1316 }
1317 }
1318
Andy Hung756ecc12018-10-19 17:47:12 -07001319 // we shouldn't truncate mixer_path
1320 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1321 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1322 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001323 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001324 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001325 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001326 if (usecase->type == PCM_CAPTURE) {
1327 struct stream_in *in = usecase->stream.in;
1328 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001329 struct listnode out_devices;
1330 list_init(&out_devices);
1331 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001332 in->ec_opened = false;
1333 }
1334 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001335 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301336 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301337
1338 if (usecase->type == PCM_CAPTURE) {
1339 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001340 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301341 ALOGD("%s: reset custom mtmx params v1", __func__);
1342 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1343 }
1344 } else {
1345 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1346 }
1347
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001348 if ((usecase->type == PCM_PLAYBACK) &&
1349 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301350 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001352 ALOGV("%s: exit", __func__);
1353 return 0;
1354}
1355
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001356int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001357 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001358{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301359 int i, num_devices = 0;
1360 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001361 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1362
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001363 if (snd_device < SND_DEVICE_MIN ||
1364 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001365 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001366 return -EINVAL;
1367 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001368
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001369 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001370 ALOGE("%s: Invalid sound device returned", __func__);
1371 return -EINVAL;
1372 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001373
1374 adev->snd_dev_ref_cnt[snd_device]++;
1375
1376 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1377 (platform_split_snd_device(adev->platform,
1378 snd_device,
1379 &num_devices,
1380 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001381 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001382 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001383 return 0;
1384 }
1385
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001386 if (audio_extn_spkr_prot_is_enabled())
1387 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001388
Aalique Grahame22e49102018-12-18 14:23:57 -08001389 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1390
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001391 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1392 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001393 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1394 goto err;
1395 }
1396 audio_extn_dev_arbi_acquire(snd_device);
1397 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001398 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001399 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001400 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001401 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001402 } else if (platform_split_snd_device(adev->platform,
1403 snd_device,
1404 &num_devices,
1405 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301406 for (i = 0; i < num_devices; i++) {
1407 enable_snd_device(adev, new_snd_devices[i]);
1408 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001409 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001410 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001411 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301412
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001413 /* enable island and power mode on supported device */
1414 if (platform_get_island_cfg_on_device(adev->platform, snd_device) &&
1415 platform_get_power_mode_on_device(adev->platform, snd_device)) {
1416 platform_set_island_cfg_on_device(adev, snd_device, true);
1417 platform_set_power_mode_on_device(adev, snd_device, true);
1418 ALOGD("%s: enable island cfg and power mode on: %s",
1419 __func__, device_name);
1420 }
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301421
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001422 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1423 (audio_extn_a2dp_start_playback() < 0)) {
1424 ALOGE(" fail to configure A2dp Source control path ");
1425 goto err;
1426 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001427
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001428 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1429 (audio_extn_a2dp_start_capture() < 0)) {
1430 ALOGE(" fail to configure A2dp Sink control path ");
1431 goto err;
1432 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301433
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001434 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1435 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1436 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1437 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1438 ALOGE(" fail to configure sco control path ");
1439 goto err;
1440 }
Zhou Song12c29502019-03-16 10:37:18 +08001441 }
1442
Zhou Song331c8e52019-08-26 14:16:12 +08001443 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001444 /* due to the possibility of calibration overwrite between listen
1445 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001446 audio_extn_sound_trigger_update_device_status(snd_device,
1447 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301448 audio_extn_listen_update_device_status(snd_device,
1449 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001450 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001451 audio_extn_sound_trigger_update_device_status(snd_device,
1452 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301453 audio_extn_listen_update_device_status(snd_device,
1454 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001455 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001456 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001457 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001458 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301459
1460 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1461 !adev->native_playback_enabled &&
1462 audio_is_true_native_stream_active(adev)) {
1463 ALOGD("%s: %d: napb: enabling native mode in hardware",
1464 __func__, __LINE__);
1465 audio_route_apply_and_update_path(adev->audio_route,
1466 "true-native-mode");
1467 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301468 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301469 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1470 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001471 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001472 ALOGD("%s: init ec ref loopback", __func__);
1473 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1474 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001476 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001477err:
1478 adev->snd_dev_ref_cnt[snd_device]--;
1479 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480}
1481
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001482int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001483 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301485 int i, num_devices = 0;
1486 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001487 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1488
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001489 if (snd_device < SND_DEVICE_MIN ||
1490 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001491 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001492 return -EINVAL;
1493 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001494
1495 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1496 ALOGE("%s: Invalid sound device returned", __func__);
1497 return -EINVAL;
1498 }
1499
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001500 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1501 ALOGE("%s: device ref cnt is already 0", __func__);
1502 return -EINVAL;
1503 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001504
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001505 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001506
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001507
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001508 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001509 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301510
Aalique Grahame22e49102018-12-18 14:23:57 -08001511 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1512
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001513 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1514 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001515 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001516
1517 // when speaker device is disabled, reset swap.
1518 // will be renabled on usecase start
1519 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001520 } else if (platform_split_snd_device(adev->platform,
1521 snd_device,
1522 &num_devices,
1523 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301524 for (i = 0; i < num_devices; i++) {
1525 disable_snd_device(adev, new_snd_devices[i]);
1526 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001527 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001528 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001529 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001530 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001531
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001532 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301533 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001534 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001535 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001536 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001537 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301538 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001539 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301540 adev->native_playback_enabled) {
1541 ALOGD("%s: %d: napb: disabling native mode in hardware",
1542 __func__, __LINE__);
1543 audio_route_reset_and_update_path(adev->audio_route,
1544 "true-native-mode");
1545 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001546 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301547 adev->asrc_mode_enabled) {
1548 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301549 disable_asrc_mode(adev);
1550 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001551 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301552 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001553 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001554 ALOGD("%s: deinit ec ref loopback", __func__);
1555 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1556 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001557
1558 audio_extn_utils_release_snd_device(snd_device);
1559 } else {
1560 if (platform_split_snd_device(adev->platform,
1561 snd_device,
1562 &num_devices,
1563 new_snd_devices) == 0) {
1564 for (i = 0; i < num_devices; i++) {
1565 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1566 }
1567 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001568 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001570 return 0;
1571}
1572
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001573/*
1574 legend:
1575 uc - existing usecase
1576 new_uc - new usecase
1577 d1, d11, d2 - SND_DEVICE enums
1578 a1, a2 - corresponding ANDROID device enums
1579 B1, B2 - backend strings
1580
1581case 1
1582 uc->dev d1 (a1) B1
1583 new_uc->dev d1 (a1), d2 (a2) B1, B2
1584
1585 resolution: disable and enable uc->dev on d1
1586
1587case 2
1588 uc->dev d1 (a1) B1
1589 new_uc->dev d11 (a1) B1
1590
1591 resolution: need to switch uc since d1 and d11 are related
1592 (e.g. speaker and voice-speaker)
1593 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1594
1595case 3
1596 uc->dev d1 (a1) B1
1597 new_uc->dev d2 (a2) B2
1598
1599 resolution: no need to switch uc
1600
1601case 4
1602 uc->dev d1 (a1) B1
1603 new_uc->dev d2 (a2) B1
1604
1605 resolution: disable enable uc-dev on d2 since backends match
1606 we cannot enable two streams on two different devices if they
1607 share the same backend. e.g. if offload is on speaker device using
1608 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1609 using the same backend, offload must also be switched to voice-handset.
1610
1611case 5
1612 uc->dev d1 (a1) B1
1613 new_uc->dev d1 (a1), d2 (a2) B1
1614
1615 resolution: disable enable uc-dev on d2 since backends match
1616 we cannot enable two streams on two different devices if they
1617 share the same backend.
1618
1619case 6
1620 uc->dev d1 (a1) B1
1621 new_uc->dev d2 (a1) B2
1622
1623 resolution: no need to switch
1624
1625case 7
1626 uc->dev d1 (a1), d2 (a2) B1, B2
1627 new_uc->dev d1 (a1) B1
1628
1629 resolution: no need to switch
1630
Zhou Song4ba65882018-07-09 14:48:07 +08001631case 8
1632 uc->dev d1 (a1) B1
1633 new_uc->dev d11 (a1), d2 (a2) B1, B2
1634 resolution: compared to case 1, for this case, d1 and d11 are related
1635 then need to do the same as case 2 to siwtch to new uc
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301636
1637case 9
1638 uc->dev d1 (a1), d2(a2) B1 B2
1639 new_uc->dev d1 (a1), d22 (a2) B1, B2
1640 resolution: disable enable uc-dev on d2 since backends match
1641 we cannot enable two streams on two different devices if they
1642 share the same backend. This is special case for combo use case
1643 with a2dp and sco devices which uses same backend.
1644 e.g. speaker-a2dp and speaker-btsco
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001645*/
1646static snd_device_t derive_playback_snd_device(void * platform,
1647 struct audio_usecase *uc,
1648 struct audio_usecase *new_uc,
1649 snd_device_t new_snd_device)
1650{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001651 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001652
1653 snd_device_t d1 = uc->out_snd_device;
1654 snd_device_t d2 = new_snd_device;
1655
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001656 list_init(&a1);
1657 list_init(&a2);
1658
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301659 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301660 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001661 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1662 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301663 break;
1664 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001665 assign_devices(&a1, &uc->stream.out->device_list);
1666 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301667 break;
1668 }
1669
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001670 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001671 if (!compare_devices(&a1, &a2) &&
1672 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001673 snd_device_t d3[2];
1674 int num_devices = 0;
1675 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001676 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001677 &num_devices,
1678 d3);
1679 if (ret < 0) {
1680 if (ret != -ENOSYS) {
1681 ALOGW("%s failed to split snd_device %d",
1682 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001683 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001684 }
1685 goto end;
1686 }
1687
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001688 if (platform_check_backends_match(d3[0], d3[1])) {
1689 return d2; // case 5
1690 } else {
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301691 if ((list_length(&a1) > 1) && (list_length(&a2) > 1) &&
1692 platform_check_backends_match(d1, d2))
1693 return d2; //case 9
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001694 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301695 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001696 // check if d1 is related to any of d3's
1697 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001698 return d1; // case 1
1699 else
1700 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001701 }
1702 } else {
1703 if (platform_check_backends_match(d1, d2)) {
1704 return d2; // case 2, 4
1705 } else {
1706 return d1; // case 6, 3
1707 }
1708 }
1709
1710end:
1711 return d2; // return whatever was calculated before.
1712}
1713
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001714static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301715 struct audio_usecase *uc_info,
1716 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001717{
1718 struct listnode *node;
1719 struct audio_usecase *usecase;
1720 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301721 snd_device_t uc_derive_snd_device;
1722 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001723 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1724 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001725 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301726 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001727 /*
1728 * This function is to make sure that all the usecases that are active on
1729 * the hardware codec backend are always routed to any one device that is
1730 * handled by the hardware codec.
1731 * For example, if low-latency and deep-buffer usecases are currently active
1732 * on speaker and out_set_parameters(headset) is received on low-latency
1733 * output, then we have to make sure deep-buffer is also switched to headset,
1734 * because of the limitation that both the devices cannot be enabled
1735 * at the same time as they share the same backend.
1736 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001737 /*
1738 * This call is to check if we need to force routing for a particular stream
1739 * If there is a backend configuration change for the device when a
1740 * new stream starts, then ADM needs to be closed and re-opened with the new
1741 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001742 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001743 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001744 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1745 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301746 /* For a2dp device reconfigure all active sessions
1747 * with new AFE encoder format based on a2dp state
1748 */
1749 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Preetam Singh Ranawatd399e6f2020-06-25 12:20:36 +05301750 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1751 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301752 audio_extn_a2dp_is_force_device_switch()) {
1753 force_routing = true;
1754 force_restart_session = true;
1755 }
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001756
1757 /*
1758 * Island cfg and power mode config needs to set before AFE port start.
1759 * Set force routing in case of voice device was enable before.
1760 */
1761 if (uc_info->type == VOICE_CALL &&
1762 voice_extn_is_voice_power_mode_supported() &&
1763 platform_check_and_update_island_power_status(adev->platform,
1764 uc_info,
1765 snd_device)) {
1766 force_routing = true;
1767 ALOGD("%s:becf: force routing %d for power mode supported device",
1768 __func__, force_routing);
1769 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301770 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1771
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001772 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001773 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001774 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001775 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1776 switch_device[i] = false;
1777
1778 list_for_each(node, &adev->usecase_list) {
1779 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001780
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301781 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1782 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301783 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301784 platform_get_snd_device_name(usecase->out_snd_device),
1785 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301786 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1787 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301788 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1789 usecase, uc_info, snd_device);
1790 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001791 (is_codec_backend_out_device_type(&usecase->device_list) ||
1792 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1793 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1794 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1795 is_a2dp_out_device_type(&usecase->device_list) ||
1796 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301797 ((force_restart_session) ||
1798 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301799 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1800 __func__, use_case_table[usecase->id],
1801 platform_get_snd_device_name(usecase->out_snd_device));
1802 disable_audio_route(adev, usecase);
1803 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301804 /* Enable existing usecase on derived playback device */
1805 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301806 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301807 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001808 }
1809 }
1810
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301811 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1812 num_uc_to_switch);
1813
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001814 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001815 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001816
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301817 /* Make sure the previous devices to be disabled first and then enable the
1818 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001819 list_for_each(node, &adev->usecase_list) {
1820 usecase = node_to_item(node, struct audio_usecase, list);
1821 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001822 /* Check if output sound device to be switched can be split and if any
1823 of the split devices match with derived sound device */
1824 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1825 &num_devices, split_snd_devices) == 0) {
1826 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1827 for (i = 0; i < num_devices; i++) {
1828 /* Disable devices that do not match with derived sound device */
1829 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1830 disable_snd_device(adev, split_snd_devices[i]);
1831 }
1832 } else {
1833 disable_snd_device(adev, usecase->out_snd_device);
1834 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001835 }
1836 }
1837
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001838 list_for_each(node, &adev->usecase_list) {
1839 usecase = node_to_item(node, struct audio_usecase, list);
1840 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001841 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1842 &num_devices, split_snd_devices) == 0) {
1843 /* Enable derived sound device only if it does not match with
1844 one of the split sound devices. This is because the matching
1845 sound device was not disabled */
1846 bool should_enable = true;
1847 for (i = 0; i < num_devices; i++) {
1848 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1849 should_enable = false;
1850 break;
1851 }
1852 }
1853 if (should_enable)
1854 enable_snd_device(adev, derive_snd_device[usecase->id]);
1855 } else {
1856 enable_snd_device(adev, derive_snd_device[usecase->id]);
1857 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001858 }
1859 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001860
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001861 /* Re-route all the usecases on the shared backend other than the
1862 specified usecase to new snd devices */
1863 list_for_each(node, &adev->usecase_list) {
1864 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301865 /* Update the out_snd_device only before enabling the audio route */
1866 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301867 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301868 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301869 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301870 use_case_table[usecase->id],
1871 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001872 /* Update voc calibration before enabling VoIP route */
1873 if (usecase->type == VOIP_CALL)
1874 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001875 usecase->out_snd_device,
1876 platform_get_input_snd_device(
1877 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301878 &uc_info->device_list,
1879 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301880 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301881 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001882 out_set_voip_volume(&usecase->stream.out->stream,
1883 usecase->stream.out->volume_l,
1884 usecase->stream.out->volume_r);
1885 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301886 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001887 }
1888 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001889 }
1890}
1891
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301892static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001893 struct audio_usecase *uc_info,
1894 snd_device_t snd_device)
1895{
1896 struct listnode *node;
1897 struct audio_usecase *usecase;
1898 bool switch_device[AUDIO_USECASE_MAX];
1899 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001900 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001901 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001902
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301903 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1904 snd_device);
1905 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301906
1907 /*
1908 * Make sure out devices is checked against out codec backend device and
1909 * also in devices against in codec backend. Checking out device against in
1910 * codec backend or vice versa causes issues.
1911 */
1912 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001913 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Kunlei Zhange7cab1a2020-05-17 20:31:05 +08001914
1915 /*
1916 * Island cfg and power mode config needs to set before AFE port start.
1917 * Set force routing in case of voice device was enable before.
1918 */
1919
1920 if (uc_info->type == VOICE_CALL &&
1921 voice_extn_is_voice_power_mode_supported() &&
1922 platform_check_and_update_island_power_status(adev->platform,
1923 uc_info,
1924 snd_device)) {
1925 force_routing = true;
1926 ALOGD("%s:becf: force routing %d for power mode supported device",
1927 __func__, force_routing);
1928 }
1929
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001930 /*
1931 * This function is to make sure that all the active capture usecases
1932 * are always routed to the same input sound device.
1933 * For example, if audio-record and voice-call usecases are currently
1934 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1935 * is received for voice call then we have to make sure that audio-record
1936 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1937 * because of the limitation that two devices cannot be enabled
1938 * at the same time if they share the same backend.
1939 */
1940 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1941 switch_device[i] = false;
1942
1943 list_for_each(node, &adev->usecase_list) {
1944 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301945 /*
1946 * TODO: Enhance below condition to handle BT sco/USB multi recording
1947 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301948
1949 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1950 (usecase->in_snd_device != snd_device || force_routing));
1951 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1952 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1953 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001954 ((backend_check_cond &&
1955 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001956 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001957 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001958 is_single_device_type_equal(&usecase->device_list,
1959 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001960 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001961 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001962 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301963 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001964 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001965 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001966 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001967 switch_device[usecase->id] = true;
1968 num_uc_to_switch++;
1969 }
1970 }
1971
1972 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001973 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001974
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301975 /* Make sure the previous devices to be disabled first and then enable the
1976 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001977 list_for_each(node, &adev->usecase_list) {
1978 usecase = node_to_item(node, struct audio_usecase, list);
1979 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001980 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001981 }
1982 }
1983
1984 list_for_each(node, &adev->usecase_list) {
1985 usecase = node_to_item(node, struct audio_usecase, list);
1986 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001987 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001988 }
1989 }
1990
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001991 /* Re-route all the usecases on the shared backend other than the
1992 specified usecase to new snd devices */
1993 list_for_each(node, &adev->usecase_list) {
1994 usecase = node_to_item(node, struct audio_usecase, list);
1995 /* Update the in_snd_device only before enabling the audio route */
1996 if (switch_device[usecase->id] ) {
1997 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001998 if (usecase->type != VOICE_CALL) {
1999 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302000 if (usecase->type == VOIP_CALL) {
2001 snd_device_t voip_snd_device;
2002 voip_snd_device = platform_get_output_snd_device(adev->platform,
2003 uc_info->stream.out,
2004 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08002005 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302006 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08002007 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05302008 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05302009 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08002010 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002011 }
2012 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002013 }
2014}
2015
Mingming Yin3a941d42016-02-17 18:08:05 -08002016static void reset_hdmi_sink_caps(struct stream_out *out) {
2017 int i = 0;
2018
2019 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
2020 out->supported_channel_masks[i] = 0;
2021 }
2022 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
2023 out->supported_formats[i] = 0;
2024 }
2025 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
2026 out->supported_sample_rates[i] = 0;
2027 }
2028}
2029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08002031static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032{
Mingming Yin3a941d42016-02-17 18:08:05 -08002033 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002034 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
2035 out->extconn.cs.controller,
2036 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037
Mingming Yin3a941d42016-02-17 18:08:05 -08002038 reset_hdmi_sink_caps(out);
2039
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002040 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002041 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002042 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08002043 out->extconn.cs.stream);
2044 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002045 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07002046 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07002047 }
2048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08002051 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002052 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08002053 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
2054 case 6:
2055 ALOGV("%s: HDMI supports 5.1 channels", __func__);
2056 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
2057 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
2058 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
2059 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
2060 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 break;
2062 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08002063 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002064 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065 break;
2066 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002067
2068 // check channel format caps
2069 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002070 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
2071 out->extconn.cs.controller,
2072 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002073 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
2074 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
2075 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
2076 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
2077 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
2078 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2079 }
2080
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002081 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2082 out->extconn.cs.controller,
2083 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002084 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2085 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2086 }
2087
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002088 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2089 out->extconn.cs.controller,
2090 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002091 ALOGV(":%s HDMI supports DTS format", __func__);
2092 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2093 }
2094
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002095 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2096 out->extconn.cs.controller,
2097 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002098 ALOGV(":%s HDMI supports DTS HD format", __func__);
2099 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2100 }
2101
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002102 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2103 out->extconn.cs.controller,
2104 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002105 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2106 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2107 }
2108
Mingming Yin3a941d42016-02-17 18:08:05 -08002109
2110 // check sample rate caps
2111 i = 0;
2112 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002113 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2114 out->extconn.cs.controller,
2115 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002116 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2117 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2118 }
2119 }
2120
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002121 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122}
2123
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002124static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2125 uint32_t *supported_sample_rates __unused,
2126 uint32_t max_rates __unused)
2127{
2128 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2129 supported_sample_rates,
2130 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302131 ssize_t i = 0;
2132
2133 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002134 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2135 supported_sample_rates[i]);
2136 }
2137 return count;
2138}
2139
2140static inline int read_usb_sup_channel_masks(bool is_playback,
2141 audio_channel_mask_t *supported_channel_masks,
2142 uint32_t max_masks)
2143{
2144 int channels = audio_extn_usb_get_max_channels(is_playback);
2145 int channel_count;
2146 uint32_t num_masks = 0;
2147 if (channels > MAX_HIFI_CHANNEL_COUNT)
2148 channels = MAX_HIFI_CHANNEL_COUNT;
2149
2150 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002151 // start from 2 channels as framework currently doesn't support mono.
2152 if (channels >= FCC_2) {
2153 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2154 }
2155 for (channel_count = FCC_2;
2156 channel_count <= channels && num_masks < max_masks;
2157 ++channel_count) {
2158 supported_channel_masks[num_masks++] =
2159 audio_channel_mask_for_index_assignment_from_count(channel_count);
2160 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002161 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002162 // For capture we report all supported channel masks from 1 channel up.
2163 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002164 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2165 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002166 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2167 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2168 if (channel_count <= FCC_2) {
2169 mask = audio_channel_in_mask_from_count(channel_count);
2170 supported_channel_masks[num_masks++] = mask;
2171 }
2172 const audio_channel_mask_t index_mask =
2173 audio_channel_mask_for_index_assignment_from_count(channel_count);
2174 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2175 supported_channel_masks[num_masks++] = index_mask;
2176 }
2177 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002178 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302179
vincenttewf51c94e2019-05-07 10:28:53 +08002180 for (size_t i = 0; i < num_masks; ++i) {
2181 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2182 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302183 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002184 return num_masks;
2185}
2186
2187static inline int read_usb_sup_formats(bool is_playback __unused,
2188 audio_format_t *supported_formats,
2189 uint32_t max_formats __unused)
2190{
2191 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2192 switch (bitwidth) {
2193 case 24:
2194 // XXX : usb.c returns 24 for s24 and s24_le?
2195 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2196 break;
2197 case 32:
2198 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2199 break;
2200 case 16:
2201 default :
2202 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2203 break;
2204 }
2205 ALOGV("%s: %s supported format %d", __func__,
2206 is_playback ? "P" : "C", bitwidth);
2207 return 1;
2208}
2209
2210static inline int read_usb_sup_params_and_compare(bool is_playback,
2211 audio_format_t *format,
2212 audio_format_t *supported_formats,
2213 uint32_t max_formats,
2214 audio_channel_mask_t *mask,
2215 audio_channel_mask_t *supported_channel_masks,
2216 uint32_t max_masks,
2217 uint32_t *rate,
2218 uint32_t *supported_sample_rates,
2219 uint32_t max_rates) {
2220 int ret = 0;
2221 int num_formats;
2222 int num_masks;
2223 int num_rates;
2224 int i;
2225
2226 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2227 max_formats);
2228 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2229 max_masks);
2230
2231 num_rates = read_usb_sup_sample_rates(is_playback,
2232 supported_sample_rates, max_rates);
2233
2234#define LUT(table, len, what, dflt) \
2235 for (i=0; i<len && (table[i] != what); i++); \
2236 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2237
2238 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2239 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2240 LUT(supported_sample_rates, num_rates, *rate, 0);
2241
2242#undef LUT
2243 return ret < 0 ? -EINVAL : 0; // HACK TBD
2244}
2245
Alexy Josephb1379942016-01-29 15:49:38 -08002246audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002247 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002248{
2249 struct audio_usecase *usecase;
2250 struct listnode *node;
2251
2252 list_for_each(node, &adev->usecase_list) {
2253 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002254 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002255 ALOGV("%s: usecase id %d", __func__, usecase->id);
2256 return usecase->id;
2257 }
2258 }
2259 return USECASE_INVALID;
2260}
2261
Alexy Josephb1379942016-01-29 15:49:38 -08002262struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002263 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002264{
2265 struct audio_usecase *usecase;
2266 struct listnode *node;
2267
2268 list_for_each(node, &adev->usecase_list) {
2269 usecase = node_to_item(node, struct audio_usecase, list);
2270 if (usecase->id == uc_id)
2271 return usecase;
2272 }
2273 return NULL;
2274}
2275
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302276/*
2277 * is a true native playback active
2278 */
2279bool audio_is_true_native_stream_active(struct audio_device *adev)
2280{
2281 bool active = false;
2282 int i = 0;
2283 struct listnode *node;
2284
2285 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2286 ALOGV("%s:napb: not in true mode or non hdphones device",
2287 __func__);
2288 active = false;
2289 goto exit;
2290 }
2291
2292 list_for_each(node, &adev->usecase_list) {
2293 struct audio_usecase *uc;
2294 uc = node_to_item(node, struct audio_usecase, list);
2295 struct stream_out *curr_out =
2296 (struct stream_out*) uc->stream.out;
2297
2298 if (curr_out && PCM_PLAYBACK == uc->type) {
2299 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2300 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2301 uc->id, curr_out->sample_rate,
2302 curr_out->bit_width,
2303 platform_get_snd_device_name(uc->out_snd_device));
2304
2305 if (is_offload_usecase(uc->id) &&
2306 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2307 active = true;
2308 ALOGD("%s:napb:native stream detected", __func__);
2309 }
2310 }
2311 }
2312exit:
2313 return active;
2314}
2315
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002316uint32_t adev_get_dsp_bit_width_enforce_mode()
2317{
2318 if (adev == NULL) {
2319 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2320 return 0;
2321 }
2322 return adev->dsp_bit_width_enforce_mode;
2323}
2324
2325static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2326{
2327 char value[PROPERTY_VALUE_MAX];
2328 int trial;
2329 uint32_t dsp_bit_width_enforce_mode = 0;
2330
2331 if (!mixer) {
2332 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2333 __func__);
2334 return 0;
2335 }
2336
2337 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2338 value, NULL) > 0) {
2339 trial = atoi(value);
2340 switch (trial) {
2341 case 16:
2342 dsp_bit_width_enforce_mode = 16;
2343 break;
2344 case 24:
2345 dsp_bit_width_enforce_mode = 24;
2346 break;
2347 case 32:
2348 dsp_bit_width_enforce_mode = 32;
2349 break;
2350 default:
2351 dsp_bit_width_enforce_mode = 0;
2352 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2353 break;
2354 }
2355 }
2356
2357 return dsp_bit_width_enforce_mode;
2358}
2359
2360static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2361 uint32_t enforce_mode,
2362 bool enable)
2363{
2364 struct mixer_ctl *ctl = NULL;
2365 const char *mixer_ctl_name = "ASM Bit Width";
2366 uint32_t asm_bit_width_mode = 0;
2367
2368 if (enforce_mode == 0) {
2369 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2370 return;
2371 }
2372
2373 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2374 if (!ctl) {
2375 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2376 __func__, mixer_ctl_name);
2377 return;
2378 }
2379
2380 if (enable)
2381 asm_bit_width_mode = enforce_mode;
2382 else
2383 asm_bit_width_mode = 0;
2384
2385 ALOGV("%s DSP bit width feature status is %d width=%d",
2386 __func__, enable, asm_bit_width_mode);
2387 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2388 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2389 asm_bit_width_mode);
2390
2391 return;
2392}
2393
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302394/*
2395 * if native DSD playback active
2396 */
2397bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2398{
2399 bool active = false;
2400 struct listnode *node = NULL;
2401 struct audio_usecase *uc = NULL;
2402 struct stream_out *curr_out = NULL;
2403
2404 list_for_each(node, &adev->usecase_list) {
2405 uc = node_to_item(node, struct audio_usecase, list);
2406 curr_out = (struct stream_out*) uc->stream.out;
2407
2408 if (curr_out && PCM_PLAYBACK == uc->type &&
2409 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2410 active = true;
2411 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302412 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302413 }
2414 }
2415 return active;
2416}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302417
2418static bool force_device_switch(struct audio_usecase *usecase)
2419{
2420 bool ret = false;
2421 bool is_it_true_mode = false;
2422
Zhou Song30f2c3e2018-02-08 14:02:15 +08002423 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302424 usecase->type == TRANSCODE_LOOPBACK_RX ||
2425 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002426 return false;
2427 }
2428
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002429 if(usecase->stream.out == NULL) {
2430 ALOGE("%s: stream.out is NULL", __func__);
2431 return false;
2432 }
2433
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302434 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002435 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002436 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2437 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302438 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2439 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2440 (!is_it_true_mode && adev->native_playback_enabled)){
2441 ret = true;
2442 ALOGD("napb: time to toggle native mode");
2443 }
2444 }
2445
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302446 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302447 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2448 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002449 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302450 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302451 ALOGD("Force a2dp device switch to update new encoder config");
2452 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002453 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302454
Florian Pfister1a84f312018-07-19 14:38:18 +02002455 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302456 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2457 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002458 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302459 return ret;
2460}
2461
Aalique Grahame22e49102018-12-18 14:23:57 -08002462static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2463{
2464 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2465}
2466
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302467bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2468{
2469 bool ret=false;
2470 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002471 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2472 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302473 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2474 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002475 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302476 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002477 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2478 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302479 ret = true;
2480
2481 return ret;
2482}
2483
2484bool is_a2dp_device(snd_device_t out_snd_device)
2485{
2486 bool ret=false;
2487 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2488 ret = true;
2489
2490 return ret;
2491}
2492
2493bool is_bt_soc_on(struct audio_device *adev)
2494{
2495 struct mixer_ctl *ctl;
2496 char *mixer_ctl_name = "BT SOC status";
2497 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2498 bool bt_soc_status = true;
2499 if (!ctl) {
2500 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2501 __func__, mixer_ctl_name);
2502 /*This is to ensure we dont break targets which dont have the kernel change*/
2503 return true;
2504 }
2505 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2506 ALOGD("BT SOC status: %d",bt_soc_status);
2507 return bt_soc_status;
2508}
2509
Zhou Song331c8e52019-08-26 14:16:12 +08002510static int configure_btsco_sample_rate(snd_device_t snd_device)
2511{
2512 struct mixer_ctl *ctl = NULL;
2513 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2514 char *rate_str = NULL;
2515 bool is_rx_dev = true;
2516
2517 if (is_btsco_device(snd_device, snd_device)) {
2518 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2519 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2520 if (!ctl_sr_tx || !ctl_sr_rx) {
2521 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2522 if (!ctl_sr)
2523 return -ENOSYS;
2524 }
2525
2526 switch (snd_device) {
2527 case SND_DEVICE_OUT_BT_SCO:
2528 rate_str = "KHZ_8";
2529 break;
2530 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2531 case SND_DEVICE_IN_BT_SCO_MIC:
2532 rate_str = "KHZ_8";
2533 is_rx_dev = false;
2534 break;
2535 case SND_DEVICE_OUT_BT_SCO_WB:
2536 rate_str = "KHZ_16";
2537 break;
2538 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2539 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2540 rate_str = "KHZ_16";
2541 is_rx_dev = false;
2542 break;
2543 default:
2544 return 0;
2545 }
2546
2547 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2548 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2549 return -ENOSYS;
2550 }
2551 return 0;
2552}
2553
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302554int out_standby_l(struct audio_stream *stream);
2555
Eric Laurent637e2d42018-11-15 12:24:31 -08002556struct stream_in *adev_get_active_input(const struct audio_device *adev)
2557{
2558 struct listnode *node;
2559 struct stream_in *last_active_in = NULL;
2560
2561 /* Get last added active input.
2562 * TODO: We may use a priority mechanism to pick highest priority active source */
2563 list_for_each(node, &adev->usecase_list)
2564 {
2565 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2566 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2567 last_active_in = usecase->stream.in;
2568 }
2569
2570 return last_active_in;
2571}
2572
2573struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2574{
2575 struct listnode *node;
2576
2577 /* First check active inputs with voice communication source and then
2578 * any input if audio mode is in communication */
2579 list_for_each(node, &adev->usecase_list)
2580 {
2581 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2582 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2583 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2584 return usecase->stream.in;
2585 }
2586 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2587 return adev_get_active_input(adev);
2588
2589 return NULL;
2590}
2591
Carter Hsu2e429db2019-05-14 18:50:52 +08002592/*
2593 * Aligned with policy.h
2594 */
2595static inline int source_priority(int inputSource)
2596{
2597 switch (inputSource) {
2598 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2599 return 9;
2600 case AUDIO_SOURCE_CAMCORDER:
2601 return 8;
2602 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2603 return 7;
2604 case AUDIO_SOURCE_UNPROCESSED:
2605 return 6;
2606 case AUDIO_SOURCE_MIC:
2607 return 5;
2608 case AUDIO_SOURCE_ECHO_REFERENCE:
2609 return 4;
2610 case AUDIO_SOURCE_FM_TUNER:
2611 return 3;
2612 case AUDIO_SOURCE_VOICE_RECOGNITION:
2613 return 2;
2614 case AUDIO_SOURCE_HOTWORD:
2615 return 1;
2616 default:
2617 break;
2618 }
2619 return 0;
2620}
2621
2622static struct stream_in *get_priority_input(struct audio_device *adev)
2623{
2624 struct listnode *node;
2625 struct audio_usecase *usecase;
2626 int last_priority = 0, priority;
2627 struct stream_in *priority_in = NULL;
2628 struct stream_in *in;
2629
2630 list_for_each(node, &adev->usecase_list) {
2631 usecase = node_to_item(node, struct audio_usecase, list);
2632 if (usecase->type == PCM_CAPTURE) {
2633 in = usecase->stream.in;
2634 if (!in)
2635 continue;
2636 priority = source_priority(in->source);
2637
2638 if (priority > last_priority) {
2639 last_priority = priority;
2640 priority_in = in;
2641 }
2642 }
2643 }
2644 return priority_in;
2645}
2646
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002647int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002649 snd_device_t out_snd_device = SND_DEVICE_NONE;
2650 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002651 struct audio_usecase *usecase = NULL;
2652 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002653 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002654 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302655 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002656 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002657 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302659 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2660
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002661 usecase = get_usecase_from_list(adev, uc_id);
2662 if (usecase == NULL) {
2663 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2664 return -EINVAL;
2665 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002667 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002668 (usecase->type == VOIP_CALL) ||
2669 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302670 if(usecase->stream.out == NULL) {
2671 ALOGE("%s: stream.out is NULL", __func__);
2672 return -EINVAL;
2673 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002674 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002675 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2676 uc_id);
2677 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2678 uc_id);
2679 } else {
2680 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302681 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002682 in_snd_device = platform_get_input_snd_device(adev->platform,
2683 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302684 &usecase->stream.out->device_list,
2685 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002686 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002687 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302688 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302689 if (usecase->stream.inout == NULL) {
2690 ALOGE("%s: stream.inout is NULL", __func__);
2691 return -EINVAL;
2692 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002693 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302694 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2695 stream_out.format = usecase->stream.inout->out_config.format;
2696 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302697 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002698 assign_devices(&usecase->device_list,
2699 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302700 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2701 if (usecase->stream.inout == NULL) {
2702 ALOGE("%s: stream.inout is NULL", __func__);
2703 return -EINVAL;
2704 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302705 struct listnode out_devices;
2706 list_init(&out_devices);
2707 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2708 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002709 assign_devices(&usecase->device_list,
2710 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002711 } else {
2712 /*
2713 * If the voice call is active, use the sound devices of voice call usecase
2714 * so that it would not result any device switch. All the usecases will
2715 * be switched to new device when select_devices() is called for voice call
2716 * usecase. This is to avoid switching devices for voice call when
2717 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002718 * choose voice call device only if the use case device is
2719 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002720 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002721 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002722 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002723 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002724 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2725 is_codec_backend_out_device_type(&usecase->device_list)) ||
2726 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2727 is_codec_backend_in_device_type(&usecase->device_list)) ||
2728 is_single_device_type_equal(&vc_usecase->device_list,
2729 AUDIO_DEVICE_OUT_HEARING_AID) ||
2730 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002731 AUDIO_DEVICE_IN_VOICE_CALL) ||
2732 (is_single_device_type_equal(&usecase->device_list,
2733 AUDIO_DEVICE_IN_USB_HEADSET) &&
2734 is_single_device_type_equal(&vc_usecase->device_list,
2735 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002736 in_snd_device = vc_usecase->in_snd_device;
2737 out_snd_device = vc_usecase->out_snd_device;
2738 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002739 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002740 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002741 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002742 if ((voip_usecase != NULL) &&
2743 (usecase->type == PCM_PLAYBACK) &&
2744 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002745 out_snd_device_backend_match = platform_check_backends_match(
2746 voip_usecase->out_snd_device,
2747 platform_get_output_snd_device(
2748 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302749 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002750 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002751 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2752 (is_codec_backend_out_device_type(&usecase->device_list) ||
2753 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002754 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002755 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002756 in_snd_device = voip_usecase->in_snd_device;
2757 out_snd_device = voip_usecase->out_snd_device;
2758 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002759 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002760 hfp_ucid = audio_extn_hfp_get_usecase();
2761 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002762 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002763 in_snd_device = hfp_usecase->in_snd_device;
2764 out_snd_device = hfp_usecase->out_snd_device;
2765 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002766 }
2767 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302768 if (usecase->stream.out == NULL) {
2769 ALOGE("%s: stream.out is NULL", __func__);
2770 return -EINVAL;
2771 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002772 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002773 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002774 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002775 struct stream_out *voip_out = adev->primary_output;
2776 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002777 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002778 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2779 else
2780 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302781 usecase->stream.out,
2782 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002783 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002784
Eric Laurent637e2d42018-11-15 12:24:31 -08002785 if (voip_usecase)
2786 voip_out = voip_usecase->stream.out;
2787
2788 if (usecase->stream.out == voip_out && voip_in != NULL)
2789 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002790 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002791 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302792 if (usecase->stream.in == NULL) {
2793 ALOGE("%s: stream.in is NULL", __func__);
2794 return -EINVAL;
2795 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002796 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002797 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002798 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002799 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002800 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002801 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002802
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002803 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002804 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002805 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2806 USECASE_AUDIO_PLAYBACK_VOIP);
2807
Carter Hsu2e429db2019-05-14 18:50:52 +08002808 usecase->stream.in->enable_ec_port = false;
2809
Zhou Song62ea0282020-03-22 19:53:01 +08002810 bool is_ha_usecase = adev->ha_proxy_enable ?
2811 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2812 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2813 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002814 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002815 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002816 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002817 } else if (adev->primary_output &&
2818 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002819 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002820 } else {
2821 /* forcing speaker o/p device to get matching i/p pair
2822 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002823 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002824 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002825 priority_in = voip_in;
2826 } else {
2827 /* get the input with the highest priority source*/
2828 priority_in = get_priority_input(adev);
2829
2830 if (!priority_in)
2831 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002832 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002833
Eric Laurent637e2d42018-11-15 12:24:31 -08002834 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002835 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302836 &out_devices,
2837 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002838 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002839 }
2840 }
2841
2842 if (out_snd_device == usecase->out_snd_device &&
2843 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302844
2845 if (!force_device_switch(usecase))
2846 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847 }
2848
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002849 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002850 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002851 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002852 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2853 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302854 }
2855
Aalique Grahame22e49102018-12-18 14:23:57 -08002856 if (out_snd_device != SND_DEVICE_NONE &&
2857 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2858 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2859 __func__,
2860 use_case_table[uc_id],
2861 adev->last_logged_snd_device[uc_id][0],
2862 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2863 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2864 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2865 -1,
2866 out_snd_device,
2867 platform_get_snd_device_name(out_snd_device),
2868 platform_get_snd_device_acdb_id(out_snd_device));
2869 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2870 }
2871 if (in_snd_device != SND_DEVICE_NONE &&
2872 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2873 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2874 __func__,
2875 use_case_table[uc_id],
2876 adev->last_logged_snd_device[uc_id][1],
2877 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2878 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2879 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2880 -1,
2881 in_snd_device,
2882 platform_get_snd_device_name(in_snd_device),
2883 platform_get_snd_device_acdb_id(in_snd_device));
2884 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2885 }
2886
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002887
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888 /*
2889 * Limitation: While in call, to do a device switch we need to disable
2890 * and enable both RX and TX devices though one of them is same as current
2891 * device.
2892 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002893 if ((usecase->type == VOICE_CALL) &&
2894 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2895 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002896 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002897 }
2898
2899 if (((usecase->type == VOICE_CALL) ||
2900 (usecase->type == VOIP_CALL)) &&
2901 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2902 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302903 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002904 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002905 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002906
2907 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302908 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002909 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002910 }
2911
Aalique Grahame22e49102018-12-18 14:23:57 -08002912 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2913 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002914 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302915 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002916 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2917 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2918 else
2919 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302920 }
2921
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002922 /* Disable current sound devices */
2923 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002924 disable_audio_route(adev, usecase);
2925 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002926 }
2927
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002928 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002929 disable_audio_route(adev, usecase);
2930 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931 }
2932
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002933 /* Applicable only on the targets that has external modem.
2934 * New device information should be sent to modem before enabling
2935 * the devices to reduce in-call device switch time.
2936 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002937 if ((usecase->type == VOICE_CALL) &&
2938 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2939 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002940 status = platform_switch_voice_call_enable_device_config(adev->platform,
2941 out_snd_device,
2942 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002943 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002944
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002945 /* Enable new sound devices */
2946 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002947 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302948 if (platform_check_codec_asrc_support(adev->platform))
2949 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002950 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951 }
2952
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002953 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302954 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002955 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002956 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002957
Avinash Vaish71a8b972014-07-24 15:36:33 +05302958 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002959 status = platform_switch_voice_call_device_post(adev->platform,
2960 out_snd_device,
2961 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302962 enable_audio_route_for_voice_usecases(adev, usecase);
2963 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002964
sangwoo170731f2013-06-08 15:36:36 +09002965 usecase->in_snd_device = in_snd_device;
2966 usecase->out_snd_device = out_snd_device;
2967
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302968 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2969 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302970 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002971 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002972 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002973 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2974 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2975 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2976 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2977 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2978 /*
2979 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2980 * configured device sample rate, if not update the COPP rate to be equal to the
2981 * device sample rate, else open COPP at stream sample rate
2982 */
2983 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2984 usecase->stream.out->sample_rate,
2985 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302986 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302987 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2988 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302989 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002990 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2991 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2992 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2993 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002994 }
2995 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002996
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002997 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002998
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002999 /* If input stream is already running then effect needs to be
3000 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08003001 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003002 check_and_enable_effect(adev);
3003
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003004 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003005 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303006 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07003007 voice_check_and_update_aanc_path(adev, out_snd_device, true);
3008
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003009 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05303010 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07003011 voice_extn_compress_voip_is_started(adev))
3012 voice_set_sidetone(adev, out_snd_device, true);
3013 }
3014
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003015 /* Applicable only on the targets that has external modem.
3016 * Enable device command should be sent to modem only after
3017 * enabling voice call mixer controls
3018 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07003019 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08003020 status = platform_switch_voice_call_usecase_route_post(adev->platform,
3021 out_snd_device,
3022 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303023
3024 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003025 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303026 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08003027 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303028 if (is_bt_soc_on(adev) == false){
3029 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08003030 if (in->pcm != NULL)
3031 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303032 }
3033 }
3034 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
3035 && usecase->stream.out->started) {
3036 if (is_bt_soc_on(adev) == false) {
3037 ALOGD("BT SCO/A2DP disconnected while in connection");
3038 out_standby_l(&usecase->stream.out->stream.common);
3039 }
3040 }
3041 } else if ((usecase->stream.out != NULL) &&
3042 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05303043 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
3044 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08003045 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303046 usecase->stream.out->started) {
3047 if (is_bt_soc_on(adev) == false) {
3048 ALOGD("BT SCO/A2dp disconnected while in connection");
3049 out_standby_l(&usecase->stream.out->stream.common);
3050 }
3051 }
3052 }
3053
Yung Ti Su70cb8242018-06-22 17:38:47 +08003054 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003055 struct stream_out *voip_out = voip_usecase->stream.out;
3056 audio_extn_utils_send_app_type_gain(adev,
3057 voip_out->app_type_cfg.app_type,
3058 &voip_out->app_type_cfg.gain[0]);
3059 }
3060
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303061 ALOGD("%s: done",__func__);
3062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063 return status;
3064}
3065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066static int stop_input_stream(struct stream_in *in)
3067{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303068 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05303070
3071 if (in == NULL) {
3072 ALOGE("%s: stream_in ptr is NULL", __func__);
3073 return -EINVAL;
3074 }
3075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08003077 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078
Eric Laurent994a6932013-07-17 11:51:42 -07003079 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003080 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081 uc_info = get_usecase_from_list(adev, in->usecase);
3082 if (uc_info == NULL) {
3083 ALOGE("%s: Could not find the usecase (%d) in the list",
3084 __func__, in->usecase);
3085 return -EINVAL;
3086 }
3087
Carter Hsu2e429db2019-05-14 18:50:52 +08003088 priority_in = get_priority_input(adev);
3089
Derek Chenea197282019-01-07 17:35:01 -08003090 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3091 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003092
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003093 /* Close in-call recording streams */
3094 voice_check_and_stop_incall_rec_usecase(adev, in);
3095
Eric Laurent150dbfe2013-02-27 14:31:02 -08003096 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003097 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003098
3099 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003100 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003102 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303103 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3104
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003105 list_remove(&uc_info->list);
3106 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107
Carter Hsu2e429db2019-05-14 18:50:52 +08003108 if (priority_in == in) {
3109 priority_in = get_priority_input(adev);
3110 if (priority_in)
3111 select_devices(adev, priority_in->usecase);
3112 }
3113
Vatsal Buchac09ae062018-11-14 13:25:08 +05303114 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003115 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 return ret;
3117}
3118
3119int start_input_stream(struct stream_in *in)
3120{
3121 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003122 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303124
3125 if (in == NULL) {
3126 ALOGE("%s: stream_in ptr is NULL", __func__);
3127 return -EINVAL;
3128 }
3129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003131 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003132 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133
Mingming Yin2664a5b2015-09-03 10:53:11 -07003134 if (get_usecase_from_list(adev, usecase) == NULL)
3135 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303136 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3137 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003138
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303139 if (CARD_STATUS_OFFLINE == in->card_status||
3140 CARD_STATUS_OFFLINE == adev->card_status) {
3141 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303142 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303143 goto error_config;
3144 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303145
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003146 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303147 if (!adev->bt_sco_on) {
3148 ALOGE("%s: SCO profile is not ready, return error", __func__);
3149 ret = -EIO;
3150 goto error_config;
3151 }
3152 }
3153
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003154 /* Check if source matches incall recording usecase criteria */
3155 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3156 if (ret)
3157 goto error_config;
3158 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003159 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3160
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303161 if (audio_extn_cin_attached_usecase(in))
3162 audio_extn_cin_acquire_usecase(in);
3163
Mingming Yin2664a5b2015-09-03 10:53:11 -07003164 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3165 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3166 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003167 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003168 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003169
Eric Laurentb23d5282013-05-14 15:27:20 -07003170 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 if (in->pcm_device_id < 0) {
3172 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3173 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003174 ret = -EINVAL;
3175 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003179
3180 if (!uc_info) {
3181 ret = -ENOMEM;
3182 goto error_config;
3183 }
3184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 uc_info->id = in->usecase;
3186 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003187 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003188 list_init(&uc_info->device_list);
3189 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003190 uc_info->in_snd_device = SND_DEVICE_NONE;
3191 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003193 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003194 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303195 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3196 adev->perf_lock_opts,
3197 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003198 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199
Derek Chenea197282019-01-07 17:35:01 -08003200 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3201 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003202
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303203 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3204
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303205 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303206 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303207 if (ret)
3208 goto error_open;
3209 else
3210 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003211 }
3212
Haynes Mathew George16081042017-05-31 17:16:49 -07003213 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003214 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003215 ALOGE("%s: pcm stream not ready", __func__);
3216 goto error_open;
3217 }
3218 ret = pcm_start(in->pcm);
3219 if (ret < 0) {
3220 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3221 goto error_open;
3222 }
3223 } else {
3224 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3225 unsigned int pcm_open_retry_count = 0;
3226
Zhou Song62ea0282020-03-22 19:53:01 +08003227 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3228 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003229 flags |= PCM_MMAP | PCM_NOIRQ;
3230 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3231 } else if (in->realtime) {
3232 flags |= PCM_MMAP | PCM_NOIRQ;
3233 }
3234
Garmond Leunge2433c32017-09-28 21:51:22 -07003235 if (audio_extn_ffv_get_stream() == in) {
3236 ALOGD("%s: ffv stream, update pcm config", __func__);
3237 audio_extn_ffv_update_pcm_config(&config);
3238 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003239 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3240 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3241
3242 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003243 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003244 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003245 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003246 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303247 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303248 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3249 adev->card_status = CARD_STATUS_OFFLINE;
3250 in->card_status = CARD_STATUS_OFFLINE;
3251 ret = -EIO;
3252 goto error_open;
3253 }
3254
Haynes Mathew George16081042017-05-31 17:16:49 -07003255 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3256 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3257 if (in->pcm != NULL) {
3258 pcm_close(in->pcm);
3259 in->pcm = NULL;
3260 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003261 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003262 ret = -EIO;
3263 goto error_open;
3264 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003265 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003266 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3267 continue;
3268 }
3269 break;
3270 }
3271
3272 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003273 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003274 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003275 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003276 if (ret < 0) {
3277 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3278 pcm_close(in->pcm);
3279 in->pcm = NULL;
3280 goto error_open;
3281 }
3282 register_in_stream(in);
3283 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003284 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003285 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003286 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003287 if (ret < 0) {
3288 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003289 pcm_close(in->pcm);
3290 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003291 goto error_open;
3292 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003293 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003294 }
3295
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003296 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003297 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3298 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003299
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003300 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303301 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3302
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303303done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003304 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303305 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003306 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303307 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003308 return ret;
3309
3310error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003311 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303312 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003314
Eric Laurentc8400632013-02-14 19:04:54 -08003315error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303316 /*
3317 * sleep 50ms to allow sufficient time for kernel
3318 * drivers to recover incases like SSR.
3319 */
3320 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003321 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303322 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003323 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324}
3325
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003326void lock_input_stream(struct stream_in *in)
3327{
3328 pthread_mutex_lock(&in->pre_lock);
3329 pthread_mutex_lock(&in->lock);
3330 pthread_mutex_unlock(&in->pre_lock);
3331}
3332
3333void lock_output_stream(struct stream_out *out)
3334{
3335 pthread_mutex_lock(&out->pre_lock);
3336 pthread_mutex_lock(&out->lock);
3337 pthread_mutex_unlock(&out->pre_lock);
3338}
3339
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003340/* must be called with out->lock locked */
3341static int send_offload_cmd_l(struct stream_out* out, int command)
3342{
3343 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3344
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003345 if (!cmd) {
3346 ALOGE("failed to allocate mem for command 0x%x", command);
3347 return -ENOMEM;
3348 }
3349
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003350 ALOGVV("%s %d", __func__, command);
3351
3352 cmd->cmd = command;
3353 list_add_tail(&out->offload_cmd_list, &cmd->node);
3354 pthread_cond_signal(&out->offload_cond);
3355 return 0;
3356}
3357
3358/* must be called iwth out->lock locked */
3359static void stop_compressed_output_l(struct stream_out *out)
3360{
3361 out->offload_state = OFFLOAD_STATE_IDLE;
3362 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003363 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003364 if (out->compr != NULL) {
3365 compress_stop(out->compr);
3366 while (out->offload_thread_blocked) {
3367 pthread_cond_wait(&out->cond, &out->lock);
3368 }
3369 }
3370}
3371
Varun Balaraje49253e2017-07-06 19:48:56 +05303372bool is_interactive_usecase(audio_usecase_t uc_id)
3373{
3374 unsigned int i;
3375 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3376 if (uc_id == interactive_usecases[i])
3377 return true;
3378 }
3379 return false;
3380}
3381
3382static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3383{
3384 audio_usecase_t ret_uc = USECASE_INVALID;
3385 unsigned int intract_uc_index;
3386 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3387
3388 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3389 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3390 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3391 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3392 ret_uc = interactive_usecases[intract_uc_index];
3393 break;
3394 }
3395 }
3396
3397 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3398 return ret_uc;
3399}
3400
3401static void free_interactive_usecase(struct audio_device *adev,
3402 audio_usecase_t uc_id)
3403{
3404 unsigned int interact_uc_index;
3405 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3406
3407 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3408 if (interactive_usecases[interact_uc_index] == uc_id) {
3409 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3410 break;
3411 }
3412 }
3413 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3414}
3415
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003416bool is_offload_usecase(audio_usecase_t uc_id)
3417{
3418 unsigned int i;
3419 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3420 if (uc_id == offload_usecases[i])
3421 return true;
3422 }
3423 return false;
3424}
3425
Dhananjay Kumarac341582017-02-23 23:42:25 +05303426static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003427{
vivek mehta446c3962015-09-14 10:57:35 -07003428 audio_usecase_t ret_uc = USECASE_INVALID;
3429 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003430 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003431 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303432 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003433 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3434 else
3435 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003436
vivek mehta446c3962015-09-14 10:57:35 -07003437 pthread_mutex_lock(&adev->lock);
3438 if (get_usecase_from_list(adev, ret_uc) != NULL)
3439 ret_uc = USECASE_INVALID;
3440 pthread_mutex_unlock(&adev->lock);
3441
3442 return ret_uc;
3443 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003444
3445 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003446 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3447 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3448 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3449 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003450 break;
3451 }
3452 }
vivek mehta446c3962015-09-14 10:57:35 -07003453
3454 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3455 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003456}
3457
3458static void free_offload_usecase(struct audio_device *adev,
3459 audio_usecase_t uc_id)
3460{
vivek mehta446c3962015-09-14 10:57:35 -07003461 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003462 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003463
3464 if (!adev->multi_offload_enable)
3465 return;
3466
3467 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3468 if (offload_usecases[offload_uc_index] == uc_id) {
3469 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003470 break;
3471 }
3472 }
3473 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3474}
3475
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003476static void *offload_thread_loop(void *context)
3477{
3478 struct stream_out *out = (struct stream_out *) context;
3479 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003480 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003481
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003482 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003483 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003484 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3485
3486 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003487 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003488 out->offload_state = OFFLOAD_STATE_IDLE;
3489 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490 for (;;) {
3491 struct offload_cmd *cmd = NULL;
3492 stream_callback_event_t event;
3493 bool send_callback = false;
3494
3495 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3496 __func__, list_empty(&out->offload_cmd_list),
3497 out->offload_state);
3498 if (list_empty(&out->offload_cmd_list)) {
3499 ALOGV("%s SLEEPING", __func__);
3500 pthread_cond_wait(&out->offload_cond, &out->lock);
3501 ALOGV("%s RUNNING", __func__);
3502 continue;
3503 }
3504
3505 item = list_head(&out->offload_cmd_list);
3506 cmd = node_to_item(item, struct offload_cmd, node);
3507 list_remove(item);
3508
3509 ALOGVV("%s STATE %d CMD %d out->compr %p",
3510 __func__, out->offload_state, cmd->cmd, out->compr);
3511
3512 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3513 free(cmd);
3514 break;
3515 }
3516
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003517 // allow OFFLOAD_CMD_ERROR reporting during standby
3518 // this is needed to handle failures during compress_open
3519 // Note however that on a pause timeout, the stream is closed
3520 // and no offload usecase will be active. Therefore this
3521 // special case is needed for compress_open failures alone
3522 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3523 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003524 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003525 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003526 pthread_cond_signal(&out->cond);
3527 continue;
3528 }
3529 out->offload_thread_blocked = true;
3530 pthread_mutex_unlock(&out->lock);
3531 send_callback = false;
3532 switch(cmd->cmd) {
3533 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003534 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003535 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003536 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003537 send_callback = true;
3538 event = STREAM_CBK_EVENT_WRITE_READY;
3539 break;
3540 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003541 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303542 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003543 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303544 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003545 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303546 if (ret < 0)
3547 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303548 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303549 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003550 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003551 else
3552 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003553 if (-ENETRESET != ret && !(-EINTR == ret &&
3554 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303555 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303556 pthread_mutex_lock(&out->lock);
3557 out->send_new_metadata = 1;
3558 out->send_next_track_params = true;
3559 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303560 event = STREAM_CBK_EVENT_DRAIN_READY;
3561 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3562 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303563 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003564 break;
3565 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003566 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003567 ret = compress_drain(out->compr);
3568 ALOGD("copl(%p):out of compress_drain", out);
3569 // EINTR check avoids drain interruption due to SSR
3570 if (-ENETRESET != ret && !(-EINTR == ret &&
3571 CARD_STATUS_OFFLINE == out->card_status)) {
3572 send_callback = true;
3573 event = STREAM_CBK_EVENT_DRAIN_READY;
3574 } else
3575 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003576 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303577 case OFFLOAD_CMD_ERROR:
3578 ALOGD("copl(%p): sending error callback to AF", out);
3579 send_callback = true;
3580 event = STREAM_CBK_EVENT_ERROR;
3581 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003582 default:
3583 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3584 break;
3585 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003586 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003587 out->offload_thread_blocked = false;
3588 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003589 if (send_callback && out->client_callback) {
3590 ALOGVV("%s: sending client_callback event %d", __func__, event);
3591 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003592 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003593 free(cmd);
3594 }
3595
3596 pthread_cond_signal(&out->cond);
3597 while (!list_empty(&out->offload_cmd_list)) {
3598 item = list_head(&out->offload_cmd_list);
3599 list_remove(item);
3600 free(node_to_item(item, struct offload_cmd, node));
3601 }
3602 pthread_mutex_unlock(&out->lock);
3603
3604 return NULL;
3605}
3606
3607static int create_offload_callback_thread(struct stream_out *out)
3608{
3609 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3610 list_init(&out->offload_cmd_list);
3611 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3612 offload_thread_loop, out);
3613 return 0;
3614}
3615
3616static int destroy_offload_callback_thread(struct stream_out *out)
3617{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003618 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003619 stop_compressed_output_l(out);
3620 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3621
3622 pthread_mutex_unlock(&out->lock);
3623 pthread_join(out->offload_thread, (void **) NULL);
3624 pthread_cond_destroy(&out->offload_cond);
3625
3626 return 0;
3627}
3628
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629static int stop_output_stream(struct stream_out *out)
3630{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303631 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 struct audio_usecase *uc_info;
3633 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003634 bool has_voip_usecase =
3635 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636
Eric Laurent994a6932013-07-17 11:51:42 -07003637 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003638 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639 uc_info = get_usecase_from_list(adev, out->usecase);
3640 if (uc_info == NULL) {
3641 ALOGE("%s: Could not find the usecase (%d) in the list",
3642 __func__, out->usecase);
3643 return -EINVAL;
3644 }
3645
Derek Chenea197282019-01-07 17:35:01 -08003646 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3647 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003648
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003649 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303650 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003651 if (adev->visualizer_stop_output != NULL)
3652 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003653
3654 audio_extn_dts_remove_state_notifier_node(out->usecase);
3655
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003656 if (adev->offload_effects_stop_output != NULL)
3657 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003658 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3659 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3660 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003661 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003662
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003663 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3664 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003665 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003666 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003667
Eric Laurent150dbfe2013-02-27 14:31:02 -08003668 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003669 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003670
3671 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003672 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673
Aalique Grahame22e49102018-12-18 14:23:57 -08003674 audio_extn_extspk_update(adev->extspk);
3675
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003676 if (is_offload_usecase(out->usecase)) {
3677 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3678 adev->dsp_bit_width_enforce_mode,
3679 false);
3680 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003681 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003682 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3683 false);
3684
3685 if (ret != 0)
3686 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3687 /* default service interval was successfully updated,
3688 reopen USB backend with new service interval */
3689 ret = 0;
3690 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003691
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003692 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303693 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003694 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303695 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003696 ALOGV("Disable passthrough , reset mixer to pcm");
3697 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003698#ifdef AUDIO_GKI_ENABLED
3699 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3700 out->compr_config.codec->reserved[0] = 0;
3701#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003702 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003703#endif
Mingming Yin21854652016-04-13 11:54:02 -07003704 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003705 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3706 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003707
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303708 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003709 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303710 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303711
Manish Dewangan21a850a2017-08-14 12:03:55 +05303712 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003713 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3714 if (ret < 0)
3715 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3716 }
3717
juyuchen2d415992018-11-16 14:15:16 +08003718 /* 1) media + voip output routing to handset must route media back to
3719 speaker when voip stops.
3720 2) trigger voip input to reroute when voip output changes to
3721 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003722 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003723 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003724 struct listnode *node;
3725 struct audio_usecase *usecase;
3726 list_for_each(node, &adev->usecase_list) {
3727 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003728 if ((usecase->type == PCM_CAPTURE &&
3729 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3730 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003731 continue;
3732
3733 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3734 __func__, usecase->id, use_case_table[usecase->id],
3735 out->usecase, use_case_table[out->usecase]);
3736 select_devices(adev, usecase->id);
3737 }
3738 }
3739
Garmond Leung5fd0b552018-04-17 11:56:12 -07003740 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003741 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 return ret;
3743}
3744
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003745struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3746 unsigned int flags, unsigned int pcm_open_retry_count,
3747 struct pcm_config *config)
3748{
3749 struct pcm* pcm = NULL;
3750
3751 while (1) {
3752 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3753 if (pcm == NULL || !pcm_is_ready(pcm)) {
3754 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3755 if (pcm != NULL) {
3756 pcm_close(pcm);
3757 pcm = NULL;
3758 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003759 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003760 return NULL;
3761
Weiyin Jiang72197252019-10-09 11:49:32 +08003762 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003763 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3764 continue;
3765 }
3766 break;
3767 }
3768
3769 if (pcm_is_ready(pcm)) {
3770 int ret = pcm_prepare(pcm);
3771 if (ret < 0) {
3772 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3773 pcm_close(pcm);
3774 pcm = NULL;
3775 }
3776 }
3777
3778 return pcm;
3779}
3780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781int start_output_stream(struct stream_out *out)
3782{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784 struct audio_usecase *uc_info;
3785 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003786 char mixer_ctl_name[128];
3787 struct mixer_ctl *ctl = NULL;
3788 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303789 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003790 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791
Haynes Mathew George380745d2017-10-04 15:27:45 -07003792 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003793 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3794 ret = -EINVAL;
3795 goto error_config;
3796 }
3797
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003798 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303799 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003800 get_device_types(&out->device_list), is_haptic_usecase);
3801
3802 bool is_speaker_active = compare_device_type(&out->device_list,
3803 AUDIO_DEVICE_OUT_SPEAKER);
3804 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3805 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303806
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303807 if (CARD_STATUS_OFFLINE == out->card_status ||
3808 CARD_STATUS_OFFLINE == adev->card_status) {
3809 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303810 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003811 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303812 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303813
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003814 //Update incall music usecase to reflect correct voice session
3815 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3816 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3817 if (ret != 0) {
3818 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3819 __func__, ret);
3820 goto error_config;
3821 }
3822 }
3823
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003824 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003825 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003826 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303827 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303828 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303829 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3830 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3831 ret = -EAGAIN;
3832 goto error_config;
3833 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303834 }
3835 }
3836 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003837 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303838 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003839 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303840 //combo usecase just by pass a2dp
3841 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003842 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303843 } else {
3844 ALOGE("%s: SCO profile is not ready, return error", __func__);
3845 ret = -EAGAIN;
3846 goto error_config;
3847 }
3848 }
3849 }
3850
Eric Laurentb23d5282013-05-14 15:27:20 -07003851 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852 if (out->pcm_device_id < 0) {
3853 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3854 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003855 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003856 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857 }
3858
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003859 if (is_haptic_usecase) {
Meng Wang51d8c2a2020-04-27 15:23:21 +08003860 adev->haptic_pcm_device_id = platform_get_pcm_device_id(
3861 USECASE_AUDIO_PLAYBACK_HAPTICS, PCM_PLAYBACK);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003862 if (adev->haptic_pcm_device_id < 0) {
3863 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3864 __func__, adev->haptic_pcm_device_id, out->usecase);
3865 ret = -EINVAL;
3866 goto error_config;
3867 }
3868 }
3869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003871
3872 if (!uc_info) {
3873 ret = -ENOMEM;
3874 goto error_config;
3875 }
3876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877 uc_info->id = out->usecase;
3878 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003879 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003880 list_init(&uc_info->device_list);
3881 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003882 uc_info->in_snd_device = SND_DEVICE_NONE;
3883 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003884
3885 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003886 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003887 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3888 /* USB backend is not reopened immediately.
3889 This is eventually done as part of select_devices */
3890 }
3891
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003892 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003893
Wei Wangf7ca6c92017-11-21 14:51:20 -08003894 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303895 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3896 adev->perf_lock_opts,
3897 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303898
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003899 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303900 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303901 if (audio_extn_passthru_is_enabled() &&
3902 audio_extn_passthru_is_passthrough_stream(out)) {
3903 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303904 }
3905 }
3906
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003907 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003908 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303909 if (!a2dp_combo) {
3910 check_a2dp_restore_l(adev, out, false);
3911 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003912 struct listnode dev;
3913 list_init(&dev);
3914 assign_devices(&dev, &out->device_list);
3915 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3916 reassign_device_list(&out->device_list,
3917 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003918 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003919 reassign_device_list(&out->device_list,
3920 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303921 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003922 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303923 }
3924 } else {
3925 select_devices(adev, out->usecase);
3926 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003927
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003928 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3929 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003930 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003931 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003932
Derek Chenea197282019-01-07 17:35:01 -08003933 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3934 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003935
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003936 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3937 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003938
3939 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003940 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003941 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3942 ALOGE("%s: pcm stream not ready", __func__);
3943 goto error_open;
3944 }
3945 ret = pcm_start(out->pcm);
3946 if (ret < 0) {
3947 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3948 goto error_open;
3949 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003950 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003951 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003952 unsigned int flags = PCM_OUT;
3953 unsigned int pcm_open_retry_count = 0;
3954 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3955 flags |= PCM_MMAP | PCM_NOIRQ;
3956 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003957 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003958 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003959 } else
3960 flags |= PCM_MONOTONIC;
3961
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003962 if ((adev->vr_audio_mode_enabled) &&
3963 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3964 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3965 "PCM_Dev %d Topology", out->pcm_device_id);
3966 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3967 if (!ctl) {
3968 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3969 __func__, mixer_ctl_name);
3970 } else {
3971 //if success use ULLPP
3972 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3973 __func__, mixer_ctl_name, out->pcm_device_id);
3974 //There is a still a possibility that some sessions
3975 // that request for FAST|RAW when 3D audio is active
3976 //can go through ULLPP. Ideally we expects apps to
3977 //listen to audio focus and stop concurrent playback
3978 //Also, we will look for mode flag (voice_in_communication)
3979 //before enabling the realtime flag.
3980 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3981 }
3982 }
3983
Surendar Karka91fa3682018-07-02 18:12:12 +05303984 if (out->realtime)
3985 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3986 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3987
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003988 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3989 flags, pcm_open_retry_count,
3990 &(out->config));
3991 if (out->pcm == NULL) {
3992 ret = -EIO;
3993 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003994 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003995
3996 if (is_haptic_usecase) {
3997 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3998 adev->haptic_pcm_device_id,
3999 flags, pcm_open_retry_count,
4000 &(adev->haptics_config));
4001 // failure to open haptics pcm shouldnt stop audio,
4002 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07004003
4004 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
4005 ALOGD("%s: enable haptic audio synchronization", __func__);
4006 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
4007 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004008 }
4009
Surendar Karka91fa3682018-07-02 18:12:12 +05304010 if (!out->realtime)
4011 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05304012 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004013
Zhou Song2b8f28f2017-09-11 10:51:38 +08004014 // apply volume for voip playback after path is set up
4015 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4016 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05304017 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4018 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304019 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
4020 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08004021 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
4022 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304023 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004024 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08004025 /*
4026 * set custom channel map if:
4027 * 1. neither mono nor stereo clips i.e. channels > 2 OR
4028 * 2. custom channel map has been set by client
4029 * else default channel map of FC/FR/FL can always be set to DSP
4030 */
4031 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
4032 platform_set_stream_channel_map(adev->platform, out->channel_mask,
4033 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08004034 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
4035 adev->dsp_bit_width_enforce_mode,
4036 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07004038 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004039 out->compr = compress_open(adev->snd_card,
4040 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004041 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004042 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05304043 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05304044 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
4045 adev->card_status = CARD_STATUS_OFFLINE;
4046 out->card_status = CARD_STATUS_OFFLINE;
4047 ret = -EIO;
4048 goto error_open;
4049 }
4050
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004051 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004052 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004053 compress_close(out->compr);
4054 out->compr = NULL;
4055 ret = -EIO;
4056 goto error_open;
4057 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304058 /* compress_open sends params of the track, so reset the flag here */
4059 out->is_compr_metadata_avail = false;
4060
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004061 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004062 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07004063
Fred Oh3f43e742015-03-04 18:42:34 -08004064 /* Since small bufs uses blocking writes, a write will be blocked
4065 for the default max poll time (20s) in the event of an SSR.
4066 Reduce the poll time to observe and deal with SSR faster.
4067 */
Ashish Jain5106d362016-05-11 19:23:33 +05304068 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08004069 compress_set_max_poll_wait(out->compr, 1000);
4070 }
4071
Manish Dewangan69426c82017-01-30 17:35:36 +05304072 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05304073 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05304074
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004075 audio_extn_dts_create_state_notifier_node(out->usecase);
4076 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4077 popcount(out->channel_mask),
4078 out->playback_started);
4079
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004080#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05304081 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08004082 audio_extn_dolby_send_ddp_endp_params(adev);
4083#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304084 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4085 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004086 if (adev->visualizer_start_output != NULL)
4087 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4088 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304089 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004090 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004091 }
Derek Chenf13dd492018-11-13 14:53:51 -08004092
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004093 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004094 /* Update cached volume from media to offload/direct stream */
4095 struct listnode *node = NULL;
4096 list_for_each(node, &adev->active_outputs_list) {
4097 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4098 streams_output_ctxt_t,
4099 list);
4100 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4101 out->volume_l = out_ctxt->output->volume_l;
4102 out->volume_r = out_ctxt->output->volume_r;
4103 }
4104 }
4105 out_set_compr_volume(&out->stream,
4106 out->volume_l, out->volume_r);
4107 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004109
4110 if (ret == 0) {
4111 register_out_stream(out);
4112 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004113 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4114 ALOGE("%s: pcm stream not ready", __func__);
4115 goto error_open;
4116 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004117 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004118 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004119 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004120 if (ret < 0)
4121 goto error_open;
4122 }
4123 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004124 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304125 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004126 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004127
vivek mehtad15d2bf2019-05-17 13:35:10 -07004128 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4129 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4130 audio_low_latency_hint_start();
4131 }
4132
Manish Dewangan21a850a2017-08-14 12:03:55 +05304133 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004134 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004135 if (ret < 0)
4136 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4137 }
4138
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004139 // consider a scenario where on pause lower layers are tear down.
4140 // so on resume, swap mixer control need to be sent only when
4141 // backend is active, hence rather than sending from enable device
4142 // sending it from start of streamtream
4143
4144 platform_set_swap_channels(adev, true);
4145
Haynes Mathew George380745d2017-10-04 15:27:45 -07004146 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304147 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004148 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004149error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004150 if (adev->haptic_pcm) {
4151 pcm_close(adev->haptic_pcm);
4152 adev->haptic_pcm = NULL;
4153 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004154 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304155 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004157error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304158 /*
4159 * sleep 50ms to allow sufficient time for kernel
4160 * drivers to recover incases like SSR.
4161 */
4162 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004163error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004164 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304165 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004166 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167}
4168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004169static int check_input_parameters(uint32_t sample_rate,
4170 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004171 int channel_count,
4172 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004174 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004175
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304176 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4177 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4178 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004179 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004180 !audio_extn_compr_cap_format_supported(format) &&
4181 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004182 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004183
Aalique Grahame22e49102018-12-18 14:23:57 -08004184 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4185 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4186 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4187 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4188 return -EINVAL;
4189 }
4190
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004191 switch (channel_count) {
4192 case 1:
4193 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304194 case 3:
4195 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004196 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004197 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304198 case 10:
4199 case 12:
4200 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004201 break;
4202 default:
4203 ret = -EINVAL;
4204 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004205
4206 switch (sample_rate) {
4207 case 8000:
4208 case 11025:
4209 case 12000:
4210 case 16000:
4211 case 22050:
4212 case 24000:
4213 case 32000:
4214 case 44100:
4215 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004216 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304217 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004218 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304219 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220 break;
4221 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004222 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223 }
4224
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004225 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226}
4227
Naresh Tanniru04f71882018-06-26 17:46:22 +05304228
4229/** Add a value in a list if not already present.
4230 * @return true if value was successfully inserted or already present,
4231 * false if the list is full and does not contain the value.
4232 */
4233static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4234 for (size_t i = 0; i < list_length; i++) {
4235 if (list[i] == value) return true; // value is already present
4236 if (list[i] == 0) { // no values in this slot
4237 list[i] = value;
4238 return true; // value inserted
4239 }
4240 }
4241 return false; // could not insert value
4242}
4243
4244/** Add channel_mask in supported_channel_masks if not already present.
4245 * @return true if channel_mask was successfully inserted or already present,
4246 * false if supported_channel_masks is full and does not contain channel_mask.
4247 */
4248static void register_channel_mask(audio_channel_mask_t channel_mask,
4249 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4250 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4251 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4252}
4253
4254/** Add format in supported_formats if not already present.
4255 * @return true if format was successfully inserted or already present,
4256 * false if supported_formats is full and does not contain format.
4257 */
4258static void register_format(audio_format_t format,
4259 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4260 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4261 "%s: stream can not declare supporting its format %x", __func__, format);
4262}
4263/** Add sample_rate in supported_sample_rates if not already present.
4264 * @return true if sample_rate was successfully inserted or already present,
4265 * false if supported_sample_rates is full and does not contain sample_rate.
4266 */
4267static void register_sample_rate(uint32_t sample_rate,
4268 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4269 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4270 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4271}
4272
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004273static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4274{
4275 uint32_t high = num1, low = num2, temp = 0;
4276
4277 if (!num1 || !num2)
4278 return 0;
4279
4280 if (num1 < num2) {
4281 high = num2;
4282 low = num1;
4283 }
4284
4285 while (low != 0) {
4286 temp = low;
4287 low = high % low;
4288 high = temp;
4289 }
4290 return (num1 * num2)/high;
4291}
4292
4293static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4294{
4295 uint32_t remainder = 0;
4296
4297 if (!multiplier)
4298 return num;
4299
4300 remainder = num % multiplier;
4301 if (remainder)
4302 num += (multiplier - remainder);
4303
4304 return num;
4305}
4306
Aalique Grahame22e49102018-12-18 14:23:57 -08004307static size_t get_stream_buffer_size(size_t duration_ms,
4308 uint32_t sample_rate,
4309 audio_format_t format,
4310 int channel_count,
4311 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004312{
4313 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004314 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004315
Aalique Grahame22e49102018-12-18 14:23:57 -08004316 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004317 if (is_low_latency)
4318 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304319
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004320 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004321 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322
Ralf Herzbd08d632018-09-28 15:50:49 +02004323 /* make sure the size is multiple of 32 bytes and additionally multiple of
4324 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004325 * At 48 kHz mono 16-bit PCM:
4326 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4327 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004328 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004329 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004330 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004331
4332 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333}
4334
Aalique Grahame22e49102018-12-18 14:23:57 -08004335static size_t get_input_buffer_size(uint32_t sample_rate,
4336 audio_format_t format,
4337 int channel_count,
4338 bool is_low_latency)
4339{
4340 /* Don't know if USB HIFI in this context so use true to be conservative */
4341 if (check_input_parameters(sample_rate, format, channel_count,
4342 true /*is_usb_hifi */) != 0)
4343 return 0;
4344
4345 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4346 sample_rate,
4347 format,
4348 channel_count,
4349 is_low_latency);
4350}
4351
Derek Chenf6318be2017-06-12 17:16:24 -04004352size_t get_output_period_size(uint32_t sample_rate,
4353 audio_format_t format,
4354 int channel_count,
4355 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304356{
4357 size_t size = 0;
4358 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4359
4360 if ((duration == 0) || (sample_rate == 0) ||
4361 (bytes_per_sample == 0) || (channel_count == 0)) {
4362 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4363 bytes_per_sample, channel_count);
4364 return -EINVAL;
4365 }
4366
4367 size = (sample_rate *
4368 duration *
4369 bytes_per_sample *
4370 channel_count) / 1000;
4371 /*
4372 * To have same PCM samples for all channels, the buffer size requires to
4373 * be multiple of (number of channels * bytes per sample)
4374 * For writes to succeed, the buffer must be written at address which is multiple of 32
4375 */
4376 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4377
4378 return (size/(channel_count * bytes_per_sample));
4379}
4380
Zhou Song48453a02018-01-10 17:50:59 +08004381static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304382{
4383 uint64_t actual_frames_rendered = 0;
Weiyin Jiang4813da12020-05-28 00:37:28 +08004384 uint64_t written_frames = 0;
4385 uint64_t kernel_frames = 0;
4386 uint64_t dsp_frames = 0;
4387 uint64_t signed_frames = 0;
4388 size_t kernel_buffer_size = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05304389
4390 /* This adjustment accounts for buffering after app processor.
4391 * It is based on estimated DSP latency per use case, rather than exact.
4392 */
Robert Lee58215542019-07-15 20:55:12 +08004393 pthread_mutex_lock(&adev->lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004394 dsp_frames = platform_render_latency(out->dev, out->usecase) *
4395 out->sample_rate / 1000000LL;
Robert Lee58215542019-07-15 20:55:12 +08004396 pthread_mutex_unlock(&adev->lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304397
Zhou Song48453a02018-01-10 17:50:59 +08004398 pthread_mutex_lock(&out->position_query_lock);
Weiyin Jiang4813da12020-05-28 00:37:28 +08004399 written_frames = out->written /
4400 (audio_bytes_per_sample(out->hal_ip_format) * popcount(out->channel_mask));
4401
Ashish Jain5106d362016-05-11 19:23:33 +05304402 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4403 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4404 * hence only estimate.
4405 */
Weiyin Jiang4813da12020-05-28 00:37:28 +08004406 kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4407 kernel_frames = kernel_buffer_size /
4408 (audio_bytes_per_sample(out->hal_op_format) * popcount(out->channel_mask));
Ashish Jain5106d362016-05-11 19:23:33 +05304409
Weiyin Jiang4813da12020-05-28 00:37:28 +08004410 if (written_frames >= (kernel_frames + dsp_frames))
4411 signed_frames = written_frames - kernel_frames - dsp_frames;
Ashish Jain5106d362016-05-11 19:23:33 +05304412
Zhou Song48453a02018-01-10 17:50:59 +08004413 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304414 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004415 if (timestamp != NULL )
4416 *timestamp = out->writeAt;
4417 } else if (timestamp != NULL) {
4418 clock_gettime(CLOCK_MONOTONIC, timestamp);
4419 }
4420 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304421
Weiyin Jiang4813da12020-05-28 00:37:28 +08004422 ALOGVV("%s signed frames %lld written frames %lld kernel frames %lld dsp frames %lld",
4423 __func__, signed_frames, written_frames, kernel_frames, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05304424
4425 return actual_frames_rendered;
4426}
4427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004428static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4429{
4430 struct stream_out *out = (struct stream_out *)stream;
4431
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004432 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004433}
4434
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004435static int out_set_sample_rate(struct audio_stream *stream __unused,
4436 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004437{
4438 return -ENOSYS;
4439}
4440
4441static size_t out_get_buffer_size(const struct audio_stream *stream)
4442{
4443 struct stream_out *out = (struct stream_out *)stream;
4444
Varun Balaraje49253e2017-07-06 19:48:56 +05304445 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304446 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304447 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304448 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4449 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4450 else
4451 return out->compr_config.fragment_size;
4452 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004453 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304454 else if (is_offload_usecase(out->usecase) &&
4455 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304456 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004457
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004458 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004459 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004460}
4461
4462static uint32_t out_get_channels(const struct audio_stream *stream)
4463{
4464 struct stream_out *out = (struct stream_out *)stream;
4465
4466 return out->channel_mask;
4467}
4468
4469static audio_format_t out_get_format(const struct audio_stream *stream)
4470{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004471 struct stream_out *out = (struct stream_out *)stream;
4472
4473 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004474}
4475
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004476static int out_set_format(struct audio_stream *stream __unused,
4477 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004478{
4479 return -ENOSYS;
4480}
4481
4482static int out_standby(struct audio_stream *stream)
4483{
4484 struct stream_out *out = (struct stream_out *)stream;
4485 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004486 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004487
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304488 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4489 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004490
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004491 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004492 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004493 if (adev->adm_deregister_stream)
4494 adev->adm_deregister_stream(adev->adm_data, out->handle);
4495
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004496 if (is_offload_usecase(out->usecase))
4497 stop_compressed_output_l(out);
4498
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004499 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004501 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4502 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304503 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004504 pthread_mutex_unlock(&adev->lock);
4505 pthread_mutex_unlock(&out->lock);
4506 ALOGD("VOIP output entered standby");
4507 return 0;
4508 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004509 if (out->pcm) {
4510 pcm_close(out->pcm);
4511 out->pcm = NULL;
4512 }
Meng Wanga09da002020-04-20 12:56:04 +08004513 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4514 if (adev->haptic_pcm) {
4515 pcm_close(adev->haptic_pcm);
4516 adev->haptic_pcm = NULL;
4517 }
4518
4519 if (adev->haptic_buffer != NULL) {
4520 free(adev->haptic_buffer);
4521 adev->haptic_buffer = NULL;
4522 adev->haptic_buffer_size = 0;
4523 }
4524 adev->haptic_pcm_device_id = 0;
4525 }
4526
Haynes Mathew George16081042017-05-31 17:16:49 -07004527 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4528 do_stop = out->playback_started;
4529 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004530
4531 if (out->mmap_shared_memory_fd >= 0) {
4532 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4533 __func__, out->mmap_shared_memory_fd);
4534 close(out->mmap_shared_memory_fd);
4535 out->mmap_shared_memory_fd = -1;
4536 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004537 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004538 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004539 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304540 out->send_next_track_params = false;
4541 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004542 out->gapless_mdata.encoder_delay = 0;
4543 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004544 if (out->compr != NULL) {
4545 compress_close(out->compr);
4546 out->compr = NULL;
4547 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004548 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004549 if (do_stop) {
4550 stop_output_stream(out);
4551 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304552 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004553 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004554 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004555 }
4556 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304557 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004558 return 0;
4559}
4560
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304561static int out_on_error(struct audio_stream *stream)
4562{
4563 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004564 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304565
4566 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004567 // always send CMD_ERROR for offload streams, this
4568 // is needed e.g. when SSR happens within compress_open
4569 // since the stream is active, offload_callback_thread is also active.
4570 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4571 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004572 }
4573 pthread_mutex_unlock(&out->lock);
4574
4575 status = out_standby(&out->stream.common);
4576
4577 lock_output_stream(out);
4578 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004579 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304580 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304581
4582 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4583 ALOGD("Setting previous card status if offline");
4584 out->prev_card_status_offline = true;
4585 }
4586
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304587 pthread_mutex_unlock(&out->lock);
4588
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004589 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304590}
4591
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304592/*
4593 *standby implementation without locks, assumes that the callee already
4594 *has taken adev and out lock.
4595 */
4596int out_standby_l(struct audio_stream *stream)
4597{
4598 struct stream_out *out = (struct stream_out *)stream;
4599 struct audio_device *adev = out->dev;
4600
4601 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4602 stream, out->usecase, use_case_table[out->usecase]);
4603
4604 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004605 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304606 if (adev->adm_deregister_stream)
4607 adev->adm_deregister_stream(adev->adm_data, out->handle);
4608
4609 if (is_offload_usecase(out->usecase))
4610 stop_compressed_output_l(out);
4611
4612 out->standby = true;
4613 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4614 voice_extn_compress_voip_close_output_stream(stream);
4615 out->started = 0;
4616 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004617 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304618 return 0;
4619 } else if (!is_offload_usecase(out->usecase)) {
4620 if (out->pcm) {
4621 pcm_close(out->pcm);
4622 out->pcm = NULL;
4623 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004624 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4625 if (adev->haptic_pcm) {
4626 pcm_close(adev->haptic_pcm);
4627 adev->haptic_pcm = NULL;
4628 }
4629
4630 if (adev->haptic_buffer != NULL) {
4631 free(adev->haptic_buffer);
4632 adev->haptic_buffer = NULL;
4633 adev->haptic_buffer_size = 0;
4634 }
4635 adev->haptic_pcm_device_id = 0;
4636 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304637 } else {
4638 ALOGD("copl(%p):standby", out);
4639 out->send_next_track_params = false;
4640 out->is_compr_metadata_avail = false;
4641 out->gapless_mdata.encoder_delay = 0;
4642 out->gapless_mdata.encoder_padding = 0;
4643 if (out->compr != NULL) {
4644 compress_close(out->compr);
4645 out->compr = NULL;
4646 }
4647 }
4648 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004649 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304650 }
4651 ALOGD("%s: exit", __func__);
4652 return 0;
4653}
4654
Aalique Grahame22e49102018-12-18 14:23:57 -08004655static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656{
Aalique Grahame22e49102018-12-18 14:23:57 -08004657 struct stream_out *out = (struct stream_out *)stream;
4658
4659 // We try to get the lock for consistency,
4660 // but it isn't necessary for these variables.
4661 // If we're not in standby, we may be blocked on a write.
4662 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4663 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4664 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4665
Andy Hunga1f48fa2019-07-01 18:14:53 -07004666 char buffer[256]; // for statistics formatting
4667 if (!is_offload_usecase(out->usecase)) {
4668 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4669 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4670 }
4671
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004672 if (out->start_latency_ms.n > 0) {
4673 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4674 dprintf(fd, " Start latency ms: %s\n", buffer);
4675 }
4676
Aalique Grahame22e49102018-12-18 14:23:57 -08004677 if (locked) {
4678 pthread_mutex_unlock(&out->lock);
4679 }
4680
4681 // dump error info
4682 (void)error_log_dump(
4683 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685 return 0;
4686}
4687
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004688static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4689{
4690 int ret = 0;
4691 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004692
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004693 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004694 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004695 return -EINVAL;
4696 }
4697
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304698 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004699
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004700 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4701 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304702 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004703 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004704 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4705 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304706 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004707 }
4708
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004709 ALOGV("%s new encoder delay %u and padding %u", __func__,
4710 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4711
4712 return 0;
4713}
4714
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004715static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4716{
4717 return out == adev->primary_output || out == adev->voice_tx_output;
4718}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004719
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304720// note: this call is safe only if the stream_cb is
4721// removed first in close_output_stream (as is done now).
4722static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4723{
4724 if (!stream || !parms)
4725 return;
4726
4727 struct stream_out *out = (struct stream_out *)stream;
4728 struct audio_device *adev = out->dev;
4729
4730 card_status_t status;
4731 int card;
4732 if (parse_snd_card_status(parms, &card, &status) < 0)
4733 return;
4734
4735 pthread_mutex_lock(&adev->lock);
4736 bool valid_cb = (card == adev->snd_card);
4737 pthread_mutex_unlock(&adev->lock);
4738
4739 if (!valid_cb)
4740 return;
4741
4742 lock_output_stream(out);
4743 if (out->card_status != status)
4744 out->card_status = status;
4745 pthread_mutex_unlock(&out->lock);
4746
4747 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4748 use_case_table[out->usecase],
4749 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4750
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304751 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304752 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304753 if (voice_is_call_state_active(adev) &&
4754 out == adev->primary_output) {
4755 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4756 pthread_mutex_lock(&adev->lock);
4757 voice_stop_call(adev);
4758 adev->mode = AUDIO_MODE_NORMAL;
4759 pthread_mutex_unlock(&adev->lock);
4760 }
4761 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304762 return;
4763}
4764
Kevin Rocardfce19002017-08-07 19:21:36 -07004765static int get_alive_usb_card(struct str_parms* parms) {
4766 int card;
4767 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4768 !audio_extn_usb_alive(card)) {
4769 return card;
4770 }
4771 return -ENODEV;
4772}
4773
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004774int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004775 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004776{
4777 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004778 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004779 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004780 bool bypass_a2dp = false;
4781 bool reconfig = false;
4782 unsigned long service_interval = 0;
4783
4784 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004785 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4786
4787 list_init(&new_devices);
4788 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004789
4790 lock_output_stream(out);
4791 pthread_mutex_lock(&adev->lock);
4792
4793 /*
4794 * When HDMI cable is unplugged the music playback is paused and
4795 * the policy manager sends routing=0. But the audioflinger continues
4796 * to write data until standby time (3sec). As the HDMI core is
4797 * turned off, the write gets blocked.
4798 * Avoid this by routing audio to speaker until standby.
4799 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004800 if (is_single_device_type_equal(&out->device_list,
4801 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004802 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004803 !audio_extn_passthru_is_passthrough_stream(out) &&
4804 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004805 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004806 }
4807 /*
4808 * When A2DP is disconnected the
4809 * music playback is paused and the policy manager sends routing=0
4810 * But the audioflinger continues to write data until standby time
4811 * (3sec). As BT is turned off, the write gets blocked.
4812 * Avoid this by routing audio to speaker until standby.
4813 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004814 if (is_a2dp_out_device_type(&out->device_list) &&
4815 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004816 !audio_extn_a2dp_source_is_ready() &&
4817 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004818 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004819 }
4820 /*
4821 * When USB headset is disconnected the music platback paused
4822 * and the policy manager send routing=0. But if the USB is connected
4823 * back before the standby time, AFE is not closed and opened
4824 * when USB is connected back. So routing to speker will guarantee
4825 * AFE reconfiguration and AFE will be opend once USB is connected again
4826 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004827 if (is_usb_out_device_type(&out->device_list) &&
4828 list_empty(&new_devices) &&
4829 !audio_extn_usb_connected(NULL)) {
4830 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4831 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004832 /* To avoid a2dp to sco overlapping / BT device improper state
4833 * check with BT lib about a2dp streaming support before routing
4834 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004835 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004836 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004837 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4838 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004839 //combo usecase just by pass a2dp
4840 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4841 bypass_a2dp = true;
4842 } else {
4843 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4844 /* update device to a2dp and don't route as BT returned error
4845 * However it is still possible a2dp routing called because
4846 * of current active device disconnection (like wired headset)
4847 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004848 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004849 pthread_mutex_unlock(&adev->lock);
4850 pthread_mutex_unlock(&out->lock);
4851 goto error;
4852 }
4853 }
4854 }
4855
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004856 // Workaround: If routing to an non existing usb device, fail gracefully
4857 // The routing request will otherwise block during 10 second
4858 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004859 if (is_usb_out_device_type(&new_devices)) {
4860 struct str_parms *parms =
4861 str_parms_create_str(get_usb_device_address(&new_devices));
4862 if (!parms)
4863 goto error;
4864 if ((card = get_alive_usb_card(parms)) >= 0) {
4865 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4866 pthread_mutex_unlock(&adev->lock);
4867 pthread_mutex_unlock(&out->lock);
4868 str_parms_destroy(parms);
4869 ret = -ENOSYS;
4870 goto error;
4871 }
4872 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004873 }
4874
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004875 // Workaround: If routing to an non existing hdmi device, fail gracefully
4876 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4877 (platform_get_edid_info_v2(adev->platform,
4878 out->extconn.cs.controller,
4879 out->extconn.cs.stream) != 0)) {
4880 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4881 pthread_mutex_unlock(&adev->lock);
4882 pthread_mutex_unlock(&out->lock);
4883 ret = -ENOSYS;
4884 goto error;
4885 }
4886
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004887 /*
4888 * select_devices() call below switches all the usecases on the same
4889 * backend to the new device. Refer to check_usecases_codec_backend() in
4890 * the select_devices(). But how do we undo this?
4891 *
4892 * For example, music playback is active on headset (deep-buffer usecase)
4893 * and if we go to ringtones and select a ringtone, low-latency usecase
4894 * will be started on headset+speaker. As we can't enable headset+speaker
4895 * and headset devices at the same time, select_devices() switches the music
4896 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4897 * So when the ringtone playback is completed, how do we undo the same?
4898 *
4899 * We are relying on the out_set_parameters() call on deep-buffer output,
4900 * once the ringtone playback is ended.
4901 * NOTE: We should not check if the current devices are same as new devices.
4902 * Because select_devices() must be called to switch back the music
4903 * playback to headset.
4904 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004905 if (!list_empty(&new_devices)) {
4906 bool same_dev = compare_devices(&out->device_list, &new_devices);
4907 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004908
4909 if (output_drives_call(adev, out)) {
4910 if (!voice_is_call_state_active(adev)) {
4911 if (adev->mode == AUDIO_MODE_IN_CALL) {
4912 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004913 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004914 service_interval =
4915 audio_extn_usb_find_service_interval(true, true /*playback*/);
4916 audio_extn_usb_set_service_interval(true /*playback*/,
4917 service_interval,
4918 &reconfig);
4919 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4920 }
4921 ret = voice_start_call(adev);
4922 }
4923 } else {
4924 adev->current_call_output = out;
4925 voice_update_devices_for_all_voice_usecases(adev);
4926 }
4927 }
4928
4929 if (!out->standby) {
4930 if (!same_dev) {
4931 ALOGV("update routing change");
4932 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4933 adev->perf_lock_opts,
4934 adev->perf_lock_opts_size);
4935 if (adev->adm_on_routing_change)
4936 adev->adm_on_routing_change(adev->adm_data,
4937 out->handle);
4938 }
4939 if (!bypass_a2dp) {
4940 select_devices(adev, out->usecase);
4941 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004942 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4943 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004944 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004945 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004946 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004947 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004948 }
4949
4950 if (!same_dev) {
4951 // on device switch force swap, lower functions will make sure
4952 // to check if swap is allowed or not.
4953 platform_set_swap_channels(adev, true);
4954 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4955 }
4956 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4957 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004958 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004959 pthread_mutex_lock(&out->compr_mute_lock);
4960 out->a2dp_compress_mute = false;
4961 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4962 pthread_mutex_unlock(&out->compr_mute_lock);
4963 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4964 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4965 }
4966 }
4967 }
4968
4969 pthread_mutex_unlock(&adev->lock);
4970 pthread_mutex_unlock(&out->lock);
4971
4972 /*handles device and call state changes*/
4973 audio_extn_extspk_update(adev->extspk);
4974
4975error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004976 ALOGV("%s: exit: code(%d)", __func__, ret);
4977 return ret;
4978}
4979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004980static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4981{
4982 struct stream_out *out = (struct stream_out *)stream;
4983 struct audio_device *adev = out->dev;
4984 struct str_parms *parms;
4985 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004986 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004987 int ext_controller = -1;
4988 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004989
sangwoobc677242013-08-08 16:53:43 +09004990 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004991 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004992 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304993 if (!parms)
4994 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004995
4996 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4997 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08004998 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004999 out->extconn.cs.controller = ext_controller;
5000 out->extconn.cs.stream = ext_stream;
5001 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
5002 use_case_table[out->usecase], out->extconn.cs.controller,
5003 out->extconn.cs.stream);
5004 }
5005
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005006 if (out == adev->primary_output) {
5007 pthread_mutex_lock(&adev->lock);
5008 audio_extn_set_parameters(adev, parms);
5009 pthread_mutex_unlock(&adev->lock);
5010 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005011 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005012 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005013 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005014
5015 audio_extn_dts_create_state_notifier_node(out->usecase);
5016 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5017 popcount(out->channel_mask),
5018 out->playback_started);
5019
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08005020 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005021 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005022
Surendar Karkaf51b5842018-04-26 11:28:38 +05305023 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
5024 sizeof(value));
5025 if (err >= 0) {
5026 if (!strncmp("true", value, sizeof("true")) || atoi(value))
5027 audio_extn_send_dual_mono_mixing_coefficients(out);
5028 }
5029
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305030 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
5031 if (err >= 0) {
5032 strlcpy(out->profile, value, sizeof(out->profile));
5033 ALOGV("updating stream profile with value '%s'", out->profile);
5034 lock_output_stream(out);
5035 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
5036 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005037 &out->device_list, out->flags,
5038 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305039 out->sample_rate, out->bit_width,
5040 out->channel_mask, out->profile,
5041 &out->app_type_cfg);
5042 pthread_mutex_unlock(&out->lock);
5043 }
5044
Alexy Joseph98988832017-01-13 14:56:59 -08005045 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005046 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
5047 // and vendor.audio.hal.output.suspend.supported is set to true
5048 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08005049 //check suspend parameter only for low latency and if the property
5050 //is enabled
5051 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
5052 ALOGI("%s: got suspend_playback %s", __func__, value);
5053 lock_output_stream(out);
5054 if (!strncmp(value, "false", 5)) {
5055 //suspend_playback=false is supposed to set QOS value back to 75%
5056 //the mixer control sent with value Enable will achieve that
5057 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5058 } else if (!strncmp (value, "true", 4)) {
5059 //suspend_playback=true is supposed to remove QOS value
5060 //resetting the mixer control will set the default value
5061 //for the mixer control which is Disable and this removes the QOS vote
5062 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
5063 } else {
5064 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
5065 " got %s", __func__, value);
5066 ret = -1;
5067 }
5068
5069 if (ret != 0) {
5070 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
5071 __func__, out->pm_qos_mixer_path, ret);
5072 }
5073
5074 pthread_mutex_unlock(&out->lock);
5075 }
5076 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07005077
Alexy Joseph98988832017-01-13 14:56:59 -08005078 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005079 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305080error:
Eric Laurent994a6932013-07-17 11:51:42 -07005081 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005082 return ret;
5083}
5084
Paul McLeana50b7332018-12-17 08:24:21 -07005085static int in_set_microphone_direction(const struct audio_stream_in *stream,
5086 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005087 struct stream_in *in = (struct stream_in *)stream;
5088
5089 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5090
5091 in->direction = dir;
5092
5093 if (in->standby)
5094 return 0;
5095
5096 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005097}
5098
5099static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005100 struct stream_in *in = (struct stream_in *)stream;
5101
5102 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5103
5104 if (zoom > 1.0 || zoom < -1.0)
5105 return -EINVAL;
5106
5107 in->zoom = zoom;
5108
5109 if (in->standby)
5110 return 0;
5111
5112 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005113}
5114
5115
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005116static bool stream_get_parameter_channels(struct str_parms *query,
5117 struct str_parms *reply,
5118 audio_channel_mask_t *supported_channel_masks) {
5119 int ret = -1;
5120 char value[512];
5121 bool first = true;
5122 size_t i, j;
5123
5124 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5125 ret = 0;
5126 value[0] = '\0';
5127 i = 0;
5128 while (supported_channel_masks[i] != 0) {
5129 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5130 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5131 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305132 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005133
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305134 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005135 first = false;
5136 break;
5137 }
5138 }
5139 i++;
5140 }
5141 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5142 }
5143 return ret == 0;
5144}
5145
5146static bool stream_get_parameter_formats(struct str_parms *query,
5147 struct str_parms *reply,
5148 audio_format_t *supported_formats) {
5149 int ret = -1;
5150 char value[256];
5151 size_t i, j;
5152 bool first = true;
5153
5154 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5155 ret = 0;
5156 value[0] = '\0';
5157 i = 0;
5158 while (supported_formats[i] != 0) {
5159 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5160 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5161 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305162 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005163 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305164 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005165 first = false;
5166 break;
5167 }
5168 }
5169 i++;
5170 }
5171 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5172 }
5173 return ret == 0;
5174}
5175
5176static bool stream_get_parameter_rates(struct str_parms *query,
5177 struct str_parms *reply,
5178 uint32_t *supported_sample_rates) {
5179
5180 int i;
5181 char value[256];
5182 int ret = -1;
5183 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5184 ret = 0;
5185 value[0] = '\0';
5186 i=0;
5187 int cursor = 0;
5188 while (supported_sample_rates[i]) {
5189 int avail = sizeof(value) - cursor;
5190 ret = snprintf(value + cursor, avail, "%s%d",
5191 cursor > 0 ? "|" : "",
5192 supported_sample_rates[i]);
5193 if (ret < 0 || ret >= avail) {
5194 // if cursor is at the last element of the array
5195 // overwrite with \0 is duplicate work as
5196 // snprintf already put a \0 in place.
5197 // else
5198 // we had space to write the '|' at value[cursor]
5199 // (which will be overwritten) or no space to fill
5200 // the first element (=> cursor == 0)
5201 value[cursor] = '\0';
5202 break;
5203 }
5204 cursor += ret;
5205 ++i;
5206 }
5207 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5208 value);
5209 }
5210 return ret >= 0;
5211}
5212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005213static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5214{
5215 struct stream_out *out = (struct stream_out *)stream;
5216 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005217 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005218 char value[256];
5219 struct str_parms *reply = str_parms_create();
5220 size_t i, j;
5221 int ret;
5222 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005223
5224 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005225 if (reply) {
5226 str_parms_destroy(reply);
5227 }
5228 if (query) {
5229 str_parms_destroy(query);
5230 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005231 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5232 return NULL;
5233 }
5234
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005235 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005236 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5237 if (ret >= 0) {
5238 value[0] = '\0';
5239 i = 0;
5240 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005241 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5242 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005243 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005244 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005245 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005246 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005247 first = false;
5248 break;
5249 }
5250 }
5251 i++;
5252 }
5253 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5254 str = str_parms_to_str(reply);
5255 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005256 voice_extn_out_get_parameters(out, query, reply);
5257 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005258 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005259
Alexy Joseph62142aa2015-11-16 15:10:34 -08005260
5261 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5262 if (ret >= 0) {
5263 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305264 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5265 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005266 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305267 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005268 } else {
5269 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305270 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005271 }
5272 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005273 if (str)
5274 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005275 str = str_parms_to_str(reply);
5276 }
5277
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005278 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5279 if (ret >= 0) {
5280 value[0] = '\0';
5281 i = 0;
5282 first = true;
5283 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005284 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5285 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005286 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005287 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005288 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005289 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005290 first = false;
5291 break;
5292 }
5293 }
5294 i++;
5295 }
5296 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005297 if (str)
5298 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005299 str = str_parms_to_str(reply);
5300 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005301
5302 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5303 if (ret >= 0) {
5304 value[0] = '\0';
5305 i = 0;
5306 first = true;
5307 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005308 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5309 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005310 if (!first) {
5311 strlcat(value, "|", sizeof(value));
5312 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005313 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005314 first = false;
5315 break;
5316 }
5317 }
5318 i++;
5319 }
5320 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5321 if (str)
5322 free(str);
5323 str = str_parms_to_str(reply);
5324 }
5325
Alexy Joseph98988832017-01-13 14:56:59 -08005326 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5327 //only low latency track supports suspend_resume
5328 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005329 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005330 if (str)
5331 free(str);
5332 str = str_parms_to_str(reply);
5333 }
5334
5335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005336 str_parms_destroy(query);
5337 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005338 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005339 return str;
5340}
5341
5342static uint32_t out_get_latency(const struct audio_stream_out *stream)
5343{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005344 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005345 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005346 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005347
Alexy Josephaa54c872014-12-03 02:46:47 -08005348 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305349 lock_output_stream(out);
5350 latency = audio_extn_utils_compress_get_dsp_latency(out);
5351 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005352 } else if ((out->realtime) ||
5353 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005354 // since the buffer won't be filled up faster than realtime,
5355 // return a smaller number
5356 if (out->config.rate)
5357 period_ms = (out->af_period_multiplier * out->config.period_size *
5358 1000) / (out->config.rate);
5359 else
5360 period_ms = 0;
Robert Lee58215542019-07-15 20:55:12 +08005361 pthread_mutex_lock(&adev->lock);
5362 latency = period_ms + platform_render_latency(out->dev, out->usecase)/1000;
5363 pthread_mutex_unlock(&adev->lock);
Alexy Josephaa54c872014-12-03 02:46:47 -08005364 } else {
5365 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005366 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005367 }
5368
Zhou Songd2537a02020-06-11 22:04:46 +08005369 if (!out->standby && is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005370 latency += audio_extn_a2dp_get_encoder_latency();
5371
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305372 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005373 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005374}
5375
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305376static float AmpToDb(float amplification)
5377{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305378 float db = DSD_VOLUME_MIN_DB;
5379 if (amplification > 0) {
5380 db = 20 * log10(amplification);
5381 if(db < DSD_VOLUME_MIN_DB)
5382 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305383 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305384 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305385}
5386
Arun Mirpuri5d170872019-03-26 13:21:31 -07005387static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5388 float right)
5389{
5390 struct stream_out *out = (struct stream_out *)stream;
5391 long volume = 0;
5392 char mixer_ctl_name[128] = "";
5393 struct audio_device *adev = out->dev;
5394 struct mixer_ctl *ctl = NULL;
5395 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5396 PCM_PLAYBACK);
5397
5398 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5399 "Playback %d Volume", pcm_device_id);
5400 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5401 if (!ctl) {
5402 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5403 __func__, mixer_ctl_name);
5404 return -EINVAL;
5405 }
5406 if (left != right)
5407 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5408 __func__, left, right);
5409 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5410 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5411 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5412 __func__, mixer_ctl_name, volume);
5413 return -EINVAL;
5414 }
5415 return 0;
5416}
5417
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305418static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5419 float right)
5420{
5421 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305422 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305423 char mixer_ctl_name[128];
5424 struct audio_device *adev = out->dev;
5425 struct mixer_ctl *ctl;
5426 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5427 PCM_PLAYBACK);
5428
5429 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5430 "Compress Playback %d Volume", pcm_device_id);
5431 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5432 if (!ctl) {
5433 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5434 __func__, mixer_ctl_name);
5435 return -EINVAL;
5436 }
5437 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5438 __func__, mixer_ctl_name, left, right);
5439 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5440 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5441 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5442
5443 return 0;
5444}
5445
Zhou Song2b8f28f2017-09-11 10:51:38 +08005446static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5447 float right)
5448{
5449 struct stream_out *out = (struct stream_out *)stream;
5450 char mixer_ctl_name[] = "App Type Gain";
5451 struct audio_device *adev = out->dev;
5452 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305453 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005454
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005455 if (!is_valid_volume(left, right)) {
5456 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5457 __func__, left, right);
5458 return -EINVAL;
5459 }
5460
Zhou Song2b8f28f2017-09-11 10:51:38 +08005461 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5462 if (!ctl) {
5463 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5464 __func__, mixer_ctl_name);
5465 return -EINVAL;
5466 }
5467
5468 set_values[0] = 0; //0: Rx Session 1:Tx Session
5469 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305470 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5471 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005472
5473 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5474 return 0;
5475}
5476
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305477static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5478 float right)
5479{
5480 struct stream_out *out = (struct stream_out *)stream;
5481 /* Volume control for pcm playback */
5482 if (left != right) {
5483 return -EINVAL;
5484 } else {
5485 char mixer_ctl_name[128];
5486 struct audio_device *adev = out->dev;
5487 struct mixer_ctl *ctl;
5488 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5489 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5490 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5491 if (!ctl) {
5492 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5493 return -EINVAL;
5494 }
5495
5496 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5497 int ret = mixer_ctl_set_value(ctl, 0, volume);
5498 if (ret < 0) {
5499 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5500 return -EINVAL;
5501 }
5502
5503 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5504
5505 return 0;
5506 }
5507}
5508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005509static int out_set_volume(struct audio_stream_out *stream, float left,
5510 float right)
5511{
Eric Laurenta9024de2013-04-04 09:19:12 -07005512 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005513 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305514 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005515
Arun Mirpuri5d170872019-03-26 13:21:31 -07005516 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005517 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5518 /* only take left channel into account: the API is for stereo anyway */
5519 out->muted = (left == 0.0f);
5520 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005521 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305522 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005523 /*
5524 * Set mute or umute on HDMI passthrough stream.
5525 * Only take left channel into account.
5526 * Mute is 0 and unmute 1
5527 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305528 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305529 } else if (out->format == AUDIO_FORMAT_DSD){
5530 char mixer_ctl_name[128] = "DSD Volume";
5531 struct audio_device *adev = out->dev;
5532 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5533
5534 if (!ctl) {
5535 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5536 __func__, mixer_ctl_name);
5537 return -EINVAL;
5538 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305539 volume[0] = (long)(AmpToDb(left));
5540 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305541 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5542 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005543 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005544 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005545 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5546 struct listnode *node = NULL;
5547 list_for_each(node, &adev->active_outputs_list) {
5548 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5549 streams_output_ctxt_t,
5550 list);
5551 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5552 out->volume_l = out_ctxt->output->volume_l;
5553 out->volume_r = out_ctxt->output->volume_r;
5554 }
5555 }
5556 if (!out->a2dp_compress_mute) {
5557 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5558 }
5559 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005560 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305561 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005562 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305563 if (!out->a2dp_compress_mute)
5564 ret = out_set_compr_volume(stream, left, right);
5565 out->volume_l = left;
5566 out->volume_r = right;
5567 pthread_mutex_unlock(&out->compr_mute_lock);
5568 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005569 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005570 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005571 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5572 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5573 if (!out->standby) {
5574 audio_extn_utils_send_app_type_gain(out->dev,
5575 out->app_type_cfg.app_type,
5576 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005577 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005578 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005579 out->volume_l = left;
5580 out->volume_r = right;
5581 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005582 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5583 ALOGV("%s: MMAP set volume called", __func__);
5584 if (!out->standby)
5585 ret = out_set_mmap_volume(stream, left, right);
5586 out->volume_l = left;
5587 out->volume_r = right;
5588 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305589 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305590 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5591 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305592 /* Volume control for pcm playback */
5593 if (!out->standby)
5594 ret = out_set_pcm_volume(stream, left, right);
5595 else
5596 out->apply_volume = true;
5597
5598 out->volume_l = left;
5599 out->volume_r = right;
5600 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005601 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5602 ALOGV("%s: bus device set volume called", __func__);
5603 if (!out->standby)
5604 ret = out_set_pcm_volume(stream, left, right);
5605 out->volume_l = left;
5606 out->volume_r = right;
5607 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005608 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005610 return -ENOSYS;
5611}
5612
Zhou Songc9672822017-08-16 16:01:39 +08005613static void update_frames_written(struct stream_out *out, size_t bytes)
5614{
5615 size_t bpf = 0;
5616
5617 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5618 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5619 bpf = 1;
5620 else if (!is_offload_usecase(out->usecase))
5621 bpf = audio_bytes_per_sample(out->format) *
5622 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005623
5624 pthread_mutex_lock(&out->position_query_lock);
5625 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005626 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005627 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5628 }
5629 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005630}
5631
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005632int split_and_write_audio_haptic_data(struct stream_out *out,
5633 const void *buffer, size_t bytes_to_write)
5634{
5635 struct audio_device *adev = out->dev;
5636
5637 int ret = 0;
5638 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5639 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5640 size_t frame_size = channel_count * bytes_per_sample;
5641 size_t frame_count = bytes_to_write / frame_size;
5642
5643 bool force_haptic_path =
5644 property_get_bool("vendor.audio.test_haptic", false);
5645
5646 // extract Haptics data from Audio buffer
5647 bool alloc_haptic_buffer = false;
5648 int haptic_channel_count = adev->haptics_config.channels;
5649 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5650 size_t audio_frame_size = frame_size - haptic_frame_size;
5651 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5652
5653 if (adev->haptic_buffer == NULL) {
5654 alloc_haptic_buffer = true;
5655 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5656 free(adev->haptic_buffer);
5657 adev->haptic_buffer_size = 0;
5658 alloc_haptic_buffer = true;
5659 }
5660
5661 if (alloc_haptic_buffer) {
5662 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005663 if(adev->haptic_buffer == NULL) {
5664 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5665 return -ENOMEM;
5666 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005667 adev->haptic_buffer_size = total_haptic_buffer_size;
5668 }
5669
5670 size_t src_index = 0, aud_index = 0, hap_index = 0;
5671 uint8_t *audio_buffer = (uint8_t *)buffer;
5672 uint8_t *haptic_buffer = adev->haptic_buffer;
5673
5674 // This is required for testing only. This works for stereo data only.
5675 // One channel is fed to audio stream and other to haptic stream for testing.
5676 if (force_haptic_path)
5677 audio_frame_size = haptic_frame_size = bytes_per_sample;
5678
5679 for (size_t i = 0; i < frame_count; i++) {
5680 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5681 audio_frame_size);
5682 aud_index += audio_frame_size;
5683 src_index += audio_frame_size;
5684
5685 if (adev->haptic_pcm)
5686 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5687 haptic_frame_size);
5688 hap_index += haptic_frame_size;
5689 src_index += haptic_frame_size;
5690
5691 // This is required for testing only.
5692 // Discard haptic channel data.
5693 if (force_haptic_path)
5694 src_index += haptic_frame_size;
5695 }
5696
5697 // write to audio pipeline
5698 ret = pcm_write(out->pcm, (void *)audio_buffer,
5699 frame_count * audio_frame_size);
5700
5701 // write to haptics pipeline
5702 if (adev->haptic_pcm)
5703 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5704 frame_count * haptic_frame_size);
5705
5706 return ret;
5707}
5708
Aalique Grahame22e49102018-12-18 14:23:57 -08005709#ifdef NO_AUDIO_OUT
5710static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5711 const void *buffer __unused, size_t bytes)
5712{
5713 struct stream_out *out = (struct stream_out *)stream;
5714
5715 /* No Output device supported other than BT for playback.
5716 * Sleep for the amount of buffer duration
5717 */
5718 lock_output_stream(out);
5719 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5720 (const struct audio_stream_out *)&out->stream) /
5721 out_get_sample_rate(&out->stream.common));
5722 pthread_mutex_unlock(&out->lock);
5723 return bytes;
5724}
5725#endif
5726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005727static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5728 size_t bytes)
5729{
5730 struct stream_out *out = (struct stream_out *)stream;
5731 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005732 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305733 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005734 const size_t frame_size = audio_stream_out_frame_size(stream);
5735 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305736 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005737 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005738
Haynes Mathew George380745d2017-10-04 15:27:45 -07005739 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005740 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305741
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305742 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005743
Dhananjay Kumarac341582017-02-23 23:42:25 +05305744 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305745 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305746 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5747 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005748 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305749 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305750 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305751 ALOGD(" %s: sound card is not active/SSR state", __func__);
5752 ret= -EIO;
5753 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305754 }
5755 }
5756
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305757 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305758 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305759 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305760 goto exit;
5761 }
5762
Haynes Mathew George16081042017-05-31 17:16:49 -07005763 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5764 ret = -EINVAL;
5765 goto exit;
5766 }
5767
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005768 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305769 !out->is_iec61937_info_available) {
5770
5771 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5772 out->is_iec61937_info_available = true;
5773 } else if (audio_extn_passthru_is_enabled()) {
5774 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305775 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305776
5777 if((out->format == AUDIO_FORMAT_DTS) ||
5778 (out->format == AUDIO_FORMAT_DTS_HD)) {
5779 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5780 buffer, bytes);
5781 if (ret) {
5782 if (ret != -ENOSYS) {
5783 out->is_iec61937_info_available = false;
5784 ALOGD("iec61937 transmission info not yet updated retry");
5785 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305786 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305787 /* if stream has started and after that there is
5788 * stream config change (iec transmission config)
5789 * then trigger select_device to update backend configuration.
5790 */
5791 out->stream_config_changed = true;
5792 pthread_mutex_lock(&adev->lock);
5793 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305794 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005795 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305796 ret = -EINVAL;
5797 goto exit;
5798 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305799 pthread_mutex_unlock(&adev->lock);
5800 out->stream_config_changed = false;
5801 out->is_iec61937_info_available = true;
5802 }
5803 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305804
Meng Wang4c32fb42020-01-16 17:57:11 +08005805#ifdef AUDIO_GKI_ENABLED
5806 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5807 compr_passthr = out->compr_config.codec->reserved[0];
5808#else
5809 compr_passthr = out->compr_config.codec->compr_passthr;
5810#endif
5811
Garmond Leung317cbf12017-09-13 16:20:50 -07005812 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005813 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305814 (out->is_iec61937_info_available == true)) {
5815 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5816 ret = -EINVAL;
5817 goto exit;
5818 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305819 }
5820 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305821
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005822 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005823 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005824 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5825 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305826 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305827 ret = -EIO;
5828 goto exit;
5829 }
5830 }
5831 }
5832
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005833 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005834 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005835 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5836
Eric Laurent150dbfe2013-02-27 14:31:02 -08005837 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005838 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5839 ret = voice_extn_compress_voip_start_output_stream(out);
5840 else
5841 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005842 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005843 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005844 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005845 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005846 goto exit;
5847 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305848 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005849 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
vivek mehtab72d08d2016-04-29 03:16:47 -07005850 if (last_known_cal_step != -1) {
5851 ALOGD("%s: retry previous failed cal level set", __func__);
5852 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305853 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005854 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305855
5856 if ((out->is_iec61937_info_available == true) &&
5857 (audio_extn_passthru_is_passthrough_stream(out))&&
5858 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5859 ret = -EINVAL;
5860 goto exit;
5861 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305862 if (out->set_dual_mono)
5863 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005864
5865 // log startup time in ms.
5866 simple_stats_log(
5867 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005868 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005869
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005870 if (adev->is_channel_status_set == false &&
5871 compare_device_type(&out->device_list,
5872 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005873 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305874 adev->is_channel_status_set = true;
5875 }
5876
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305877 if ((adev->use_old_pspd_mix_ctrl == true) &&
5878 (out->pspd_coeff_sent == false)) {
5879 /*
5880 * Need to resend pspd coefficients after stream started for
5881 * older kernel version as it does not save the coefficients
5882 * and also stream has to be started for coeff to apply.
5883 */
5884 usecase = get_usecase_from_list(adev, out->usecase);
5885 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305886 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305887 out->pspd_coeff_sent = true;
5888 }
5889 }
5890
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005891 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005892 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005893 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005894 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005895 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5896 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305897 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5898 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005899 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305900 out->send_next_track_params = false;
5901 out->is_compr_metadata_avail = false;
5902 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005903 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305904 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305905 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005906
Ashish Jain83a6cc22016-06-28 14:34:17 +05305907 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305908 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305909 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305910 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005911 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305912 return -EINVAL;
5913 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305914 audio_format_t dst_format = out->hal_op_format;
5915 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305916
Dieter Luecking5d57def2018-09-07 14:23:37 +02005917 /* prevent division-by-zero */
5918 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5919 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5920 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5921 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305922 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005923 ATRACE_END();
5924 return -EINVAL;
5925 }
5926
Ashish Jainf1eaa582016-05-23 20:54:24 +05305927 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5928 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5929
Ashish Jain83a6cc22016-06-28 14:34:17 +05305930 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305931 dst_format,
5932 buffer,
5933 src_format,
5934 frames);
5935
Ashish Jain83a6cc22016-06-28 14:34:17 +05305936 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305937 bytes_to_write);
5938
5939 /*Convert written bytes in audio flinger format*/
5940 if (ret > 0)
5941 ret = ((ret * format_to_bitwidth_table[out->format]) /
5942 format_to_bitwidth_table[dst_format]);
5943 }
5944 } else
5945 ret = compress_write(out->compr, buffer, bytes);
5946
Zhou Songc9672822017-08-16 16:01:39 +08005947 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5948 update_frames_written(out, bytes);
5949
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305950 if (ret < 0)
5951 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005952 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305953 /*msg to cb thread only if non blocking write is enabled*/
5954 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305955 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005956 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305957 } else if (-ENETRESET == ret) {
5958 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305959 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305960 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305961 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005962 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305963 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005964 }
Ashish Jain5106d362016-05-11 19:23:33 +05305965
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305966 /* Call compr start only when non-zero bytes of data is there to be rendered */
5967 if (!out->playback_started && ret > 0) {
5968 int status = compress_start(out->compr);
5969 if (status < 0) {
5970 ret = status;
5971 ALOGE("%s: compr start failed with err %d", __func__, errno);
5972 goto exit;
5973 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005974 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005975 out->playback_started = 1;
5976 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005977
5978 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5979 popcount(out->channel_mask),
5980 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005981 }
5982 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005983 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005984 return ret;
5985 } else {
5986 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005987 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005988 if (out->muted)
5989 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005990 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5991 __func__, frames, frame_size, bytes_to_write);
5992
Aalique Grahame22e49102018-12-18 14:23:57 -08005993 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005994 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5995 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5996 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005997 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5998 int16_t *src = (int16_t *)buffer;
5999 int16_t *dst = (int16_t *)buffer;
6000
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006001 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006002 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08006003 "out_write called for %s use case with wrong properties",
6004 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006005
6006 /*
6007 * FIXME: this can be removed once audio flinger mixer supports
6008 * mono output
6009 */
6010
6011 /*
6012 * Code below goes over each frame in the buffer and adds both
6013 * L and R samples and then divides by 2 to convert to mono
6014 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08006015 if (channel_count == 2) {
6016 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
6017 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
6018 }
6019 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006020 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006021 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07006022
6023 // Note: since out_get_presentation_position() is called alternating with out_write()
6024 // by AudioFlinger, we can check underruns using the prior timestamp read.
6025 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
6026 if (out->last_fifo_valid) {
6027 // compute drain to see if there is an underrun.
6028 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
6029 const int64_t frames_by_time =
6030 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
6031 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
6032
6033 if (underrun > 0) {
6034 simple_stats_log(&out->fifo_underruns, underrun);
6035
6036 ALOGW("%s: underrun(%lld) "
6037 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
6038 __func__,
6039 (long long)out->fifo_underruns.n,
6040 (long long)frames_by_time,
6041 (long long)out->last_fifo_frames_remaining);
6042 }
6043 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
6044 }
6045
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306046 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006047
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006048 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006049
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006050 if (out->config.rate)
6051 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
6052 out->config.rate;
6053
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006054 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006055 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
6056
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006057 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07006058 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006059 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05306060 out->convert_buffer != NULL) {
6061
6062 memcpy_by_audio_format(out->convert_buffer,
6063 out->hal_op_format,
6064 buffer,
6065 out->hal_ip_format,
6066 out->config.period_size * out->config.channels);
6067
6068 ret = pcm_write(out->pcm, out->convert_buffer,
6069 (out->config.period_size *
6070 out->config.channels *
6071 format_to_bitwidth_table[out->hal_op_format]));
6072 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05306073 /*
6074 * To avoid underrun in DSP when the application is not pumping
6075 * data at required rate, check for the no. of bytes and ignore
6076 * pcm_write if it is less than actual buffer size.
6077 * It is a work around to a change in compress VOIP driver.
6078 */
6079 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
6080 bytes < (out->config.period_size * out->config.channels *
6081 audio_bytes_per_sample(out->format))) {
6082 size_t voip_buf_size =
6083 out->config.period_size * out->config.channels *
6084 audio_bytes_per_sample(out->format);
6085 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
6086 __func__, bytes, voip_buf_size);
6087 usleep(((uint64_t)voip_buf_size - bytes) *
6088 1000000 / audio_stream_out_frame_size(stream) /
6089 out_get_sample_rate(&out->stream.common));
6090 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006091 } else {
6092 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6093 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6094 else
6095 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6096 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306097 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006098
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006099 release_out_focus(out);
6100
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306101 if (ret < 0)
6102 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006103 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306104 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006105 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006106 }
6107
6108exit:
Zhou Songc9672822017-08-16 16:01:39 +08006109 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306110 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306111 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306112 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006113 pthread_mutex_unlock(&out->lock);
6114
6115 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006116 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006117 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306118 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306119 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306120 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306121 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306122 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306123 out->standby = true;
6124 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306125 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006126 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6127 /* prevent division-by-zero */
6128 uint32_t stream_size = audio_stream_out_frame_size(stream);
6129 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006130
Dieter Luecking5d57def2018-09-07 14:23:37 +02006131 if ((stream_size == 0) || (srate == 0)) {
6132 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6133 ATRACE_END();
6134 return -EINVAL;
6135 }
6136 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6137 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006138 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306139 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006140 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006141 return ret;
6142 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006143 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006144 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006145 return bytes;
6146}
6147
6148static int out_get_render_position(const struct audio_stream_out *stream,
6149 uint32_t *dsp_frames)
6150{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006151 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006152
6153 if (dsp_frames == NULL)
6154 return -EINVAL;
6155
6156 *dsp_frames = 0;
6157 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006158 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306159
6160 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6161 * this operation and adev_close_output_stream(where out gets reset).
6162 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306163 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006164 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306165 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006166 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306167 return 0;
6168 }
6169
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006170 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306171 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306172 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006173 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306174 if (ret < 0)
6175 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006176 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306177 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006178 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306179 if (-ENETRESET == ret) {
6180 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306181 out->card_status = CARD_STATUS_OFFLINE;
6182 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306183 } else if(ret < 0) {
6184 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306185 ret = -EINVAL;
6186 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306187 /*
6188 * Handle corner case where compress session is closed during SSR
6189 * and timestamp is queried
6190 */
6191 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306192 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306193 } else if (out->prev_card_status_offline) {
6194 ALOGE("ERROR: previously sound card was offline,return error");
6195 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306196 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306197 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006198 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306199 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306200 pthread_mutex_unlock(&out->lock);
6201 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006202 } else if (audio_is_linear_pcm(out->format)) {
6203 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006204 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006205 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006206 } else
6207 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006208}
6209
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006210static int out_add_audio_effect(const struct audio_stream *stream __unused,
6211 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006212{
6213 return 0;
6214}
6215
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006216static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6217 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006218{
6219 return 0;
6220}
6221
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006222static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6223 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006224{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306225 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006226}
6227
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006228static int out_get_presentation_position(const struct audio_stream_out *stream,
6229 uint64_t *frames, struct timespec *timestamp)
6230{
6231 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306232 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006233 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006234
Ashish Jain5106d362016-05-11 19:23:33 +05306235 /* below piece of code is not guarded against any lock because audioFliner serializes
6236 * this operation and adev_close_output_stream( where out gets reset).
6237 */
6238 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306239 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006240 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306241 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6242 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6243 return 0;
6244 }
6245
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006246 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006247
Ashish Jain5106d362016-05-11 19:23:33 +05306248 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6249 ret = compress_get_tstamp(out->compr, &dsp_frames,
6250 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006251 // Adjustment accounts for A2dp encoder latency with offload usecases
6252 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006253 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006254 unsigned long offset =
6255 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6256 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6257 }
Ashish Jain5106d362016-05-11 19:23:33 +05306258 ALOGVV("%s rendered frames %ld sample_rate %d",
6259 __func__, dsp_frames, out->sample_rate);
6260 *frames = dsp_frames;
6261 if (ret < 0)
6262 ret = -errno;
6263 if (-ENETRESET == ret) {
6264 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306265 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306266 ret = -EINVAL;
6267 } else
6268 ret = 0;
6269 /* this is the best we can do */
6270 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006271 } else {
6272 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006273 unsigned int avail;
6274 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006275 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006276 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006277
Andy Hunga1f48fa2019-07-01 18:14:53 -07006278 if (out->kernel_buffer_size > avail) {
6279 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6280 } else {
6281 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6282 __func__, avail, out->kernel_buffer_size);
6283 avail = out->kernel_buffer_size;
6284 frames_temp = out->last_fifo_frames_remaining = 0;
6285 }
6286 out->last_fifo_valid = true;
6287 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6288
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006289 if (out->written >= frames_temp)
6290 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006291
Andy Hunga1f48fa2019-07-01 18:14:53 -07006292 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6293 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6294
Weiyin Jiangd4633762018-03-16 12:05:03 +08006295 // This adjustment accounts for buffering after app processor.
6296 // It is based on estimated DSP latency per use case, rather than exact.
Robert Lee58215542019-07-15 20:55:12 +08006297 pthread_mutex_lock(&adev->lock);
6298 frames_temp = platform_render_latency(out->dev, out->usecase) *
6299 out->sample_rate / 1000000LL;
6300 pthread_mutex_unlock(&adev->lock);
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006301 if (signed_frames >= frames_temp)
6302 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006303
Weiyin Jiangd4633762018-03-16 12:05:03 +08006304 // Adjustment accounts for A2dp encoder latency with non offload usecases
6305 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006306 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006307 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6308 if (signed_frames >= frames_temp)
6309 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006310 }
6311
6312 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006313 *frames = signed_frames;
6314 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006315 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006316 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6317 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006318 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306319 *frames = out->written;
6320 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306321 if (is_offload_usecase(out->usecase))
6322 ret = -EINVAL;
6323 else
6324 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006325 }
6326 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006327 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006328 return ret;
6329}
6330
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006331static int out_set_callback(struct audio_stream_out *stream,
6332 stream_callback_t callback, void *cookie)
6333{
6334 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006335 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006336
6337 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006338 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006339 out->client_callback = callback;
6340 out->client_cookie = cookie;
6341 if (out->adsp_hdlr_stream_handle) {
6342 ret = audio_extn_adsp_hdlr_stream_set_callback(
6343 out->adsp_hdlr_stream_handle,
6344 callback,
6345 cookie);
6346 if (ret)
6347 ALOGW("%s:adsp hdlr callback registration failed %d",
6348 __func__, ret);
6349 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006350 pthread_mutex_unlock(&out->lock);
6351 return 0;
6352}
6353
6354static int out_pause(struct audio_stream_out* stream)
6355{
6356 struct stream_out *out = (struct stream_out *)stream;
6357 int status = -ENOSYS;
6358 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006359 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006360 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306361 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006362 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006363 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306364 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306365 status = compress_pause(out->compr);
6366
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006367 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006368
Mingming Yin21854652016-04-13 11:54:02 -07006369 if (audio_extn_passthru_is_active()) {
6370 ALOGV("offload use case, pause passthru");
6371 audio_extn_passthru_on_pause(out);
6372 }
6373
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306374 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006375 audio_extn_dts_notify_playback_state(out->usecase, 0,
6376 out->sample_rate, popcount(out->channel_mask),
6377 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006378 }
6379 pthread_mutex_unlock(&out->lock);
6380 }
6381 return status;
6382}
6383
6384static int out_resume(struct audio_stream_out* stream)
6385{
6386 struct stream_out *out = (struct stream_out *)stream;
6387 int status = -ENOSYS;
6388 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006389 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006390 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306391 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006392 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006393 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306394 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306395 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006396 }
6397 if (!status) {
6398 out->offload_state = OFFLOAD_STATE_PLAYING;
6399 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306400 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006401 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6402 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006403 }
6404 pthread_mutex_unlock(&out->lock);
6405 }
6406 return status;
6407}
6408
6409static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6410{
6411 struct stream_out *out = (struct stream_out *)stream;
6412 int status = -ENOSYS;
6413 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006414 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006415 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006416 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6417 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6418 else
6419 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6420 pthread_mutex_unlock(&out->lock);
6421 }
6422 return status;
6423}
6424
6425static int out_flush(struct audio_stream_out* stream)
6426{
6427 struct stream_out *out = (struct stream_out *)stream;
6428 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006429 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006430 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006431 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006432 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6433 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006434 } else {
6435 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6436 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006437 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006438 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006439 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006440 return 0;
6441 }
6442 return -ENOSYS;
6443}
6444
Haynes Mathew George16081042017-05-31 17:16:49 -07006445static int out_stop(const struct audio_stream_out* stream)
6446{
6447 struct stream_out *out = (struct stream_out *)stream;
6448 struct audio_device *adev = out->dev;
6449 int ret = -ENOSYS;
6450
6451 ALOGV("%s", __func__);
6452 pthread_mutex_lock(&adev->lock);
6453 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6454 out->playback_started && out->pcm != NULL) {
6455 pcm_stop(out->pcm);
6456 ret = stop_output_stream(out);
6457 out->playback_started = false;
6458 }
6459 pthread_mutex_unlock(&adev->lock);
6460 return ret;
6461}
6462
6463static int out_start(const struct audio_stream_out* stream)
6464{
6465 struct stream_out *out = (struct stream_out *)stream;
6466 struct audio_device *adev = out->dev;
6467 int ret = -ENOSYS;
6468
6469 ALOGV("%s", __func__);
6470 pthread_mutex_lock(&adev->lock);
6471 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6472 !out->playback_started && out->pcm != NULL) {
6473 ret = start_output_stream(out);
6474 if (ret == 0) {
6475 out->playback_started = true;
6476 }
6477 }
6478 pthread_mutex_unlock(&adev->lock);
6479 return ret;
6480}
6481
6482/*
6483 * Modify config->period_count based on min_size_frames
6484 */
6485static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6486{
6487 int periodCountRequested = (min_size_frames + config->period_size - 1)
6488 / config->period_size;
6489 int periodCount = MMAP_PERIOD_COUNT_MIN;
6490
6491 ALOGV("%s original config.period_size = %d config.period_count = %d",
6492 __func__, config->period_size, config->period_count);
6493
6494 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6495 periodCount *= 2;
6496 }
6497 config->period_count = periodCount;
6498
6499 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6500}
6501
Phil Burkfe17efd2019-03-25 10:23:35 -07006502// Read offset for the positional timestamp from a persistent vendor property.
6503// This is to workaround apparent inaccuracies in the timing information that
6504// is used by the AAudio timing model. The inaccuracies can cause glitches.
6505static int64_t get_mmap_out_time_offset() {
6506 const int32_t kDefaultOffsetMicros = 0;
6507 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006508 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006509 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6510 return mmap_time_offset_micros * (int64_t)1000;
6511}
6512
Haynes Mathew George16081042017-05-31 17:16:49 -07006513static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6514 int32_t min_size_frames,
6515 struct audio_mmap_buffer_info *info)
6516{
6517 struct stream_out *out = (struct stream_out *)stream;
6518 struct audio_device *adev = out->dev;
6519 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006520 unsigned int offset1 = 0;
6521 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006522 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006523 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006524 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006525
Arun Mirpuri5d170872019-03-26 13:21:31 -07006526 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306527 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006528 pthread_mutex_lock(&adev->lock);
6529
Sharad Sanglec6f32552018-05-04 16:15:38 +05306530 if (CARD_STATUS_OFFLINE == out->card_status ||
6531 CARD_STATUS_OFFLINE == adev->card_status) {
6532 ALOGW("out->card_status or adev->card_status offline, try again");
6533 ret = -EIO;
6534 goto exit;
6535 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306536 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006537 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6538 ret = -EINVAL;
6539 goto exit;
6540 }
6541 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6542 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6543 ret = -ENOSYS;
6544 goto exit;
6545 }
6546 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6547 if (out->pcm_device_id < 0) {
6548 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6549 __func__, out->pcm_device_id, out->usecase);
6550 ret = -EINVAL;
6551 goto exit;
6552 }
6553
6554 adjust_mmap_period_count(&out->config, min_size_frames);
6555
Arun Mirpuri5d170872019-03-26 13:21:31 -07006556 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006557 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6558 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6559 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306560 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306561 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6562 out->card_status = CARD_STATUS_OFFLINE;
6563 adev->card_status = CARD_STATUS_OFFLINE;
6564 ret = -EIO;
6565 goto exit;
6566 }
6567
Haynes Mathew George16081042017-05-31 17:16:49 -07006568 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6569 step = "open";
6570 ret = -ENODEV;
6571 goto exit;
6572 }
6573 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6574 if (ret < 0) {
6575 step = "begin";
6576 goto exit;
6577 }
juyuchen626833d2019-06-04 16:48:02 +08006578
6579 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006580 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006581 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006582 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006583 ret = platform_get_mmap_data_fd(adev->platform,
6584 out->pcm_device_id, 0 /*playback*/,
6585 &info->shared_memory_fd,
6586 &mmap_size);
6587 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006588 // Fall back to non exclusive mode
6589 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6590 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006591 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6592 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6593
Arun Mirpuri5d170872019-03-26 13:21:31 -07006594 if (mmap_size < buffer_size) {
6595 step = "mmap";
6596 goto exit;
6597 }
juyuchen626833d2019-06-04 16:48:02 +08006598 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006599 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006600 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006601 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006602
6603 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6604 if (ret < 0) {
6605 step = "commit";
6606 goto exit;
6607 }
6608
Phil Burkfe17efd2019-03-25 10:23:35 -07006609 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6610
Haynes Mathew George16081042017-05-31 17:16:49 -07006611 out->standby = false;
6612 ret = 0;
6613
Arun Mirpuri5d170872019-03-26 13:21:31 -07006614 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006615 __func__, info->shared_memory_address, info->buffer_size_frames);
6616
6617exit:
6618 if (ret != 0) {
6619 if (out->pcm == NULL) {
6620 ALOGE("%s: %s - %d", __func__, step, ret);
6621 } else {
6622 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6623 pcm_close(out->pcm);
6624 out->pcm = NULL;
6625 }
6626 }
6627 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306628 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006629 return ret;
6630}
6631
6632static int out_get_mmap_position(const struct audio_stream_out *stream,
6633 struct audio_mmap_position *position)
6634{
6635 struct stream_out *out = (struct stream_out *)stream;
6636 ALOGVV("%s", __func__);
6637 if (position == NULL) {
6638 return -EINVAL;
6639 }
6640 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006641 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006642 return -ENOSYS;
6643 }
6644 if (out->pcm == NULL) {
6645 return -ENOSYS;
6646 }
6647
6648 struct timespec ts = { 0, 0 };
6649 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6650 if (ret < 0) {
6651 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6652 return ret;
6653 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006654 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6655 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006656 return 0;
6657}
6658
6659
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006660/** audio_stream_in implementation **/
6661static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6662{
6663 struct stream_in *in = (struct stream_in *)stream;
6664
6665 return in->config.rate;
6666}
6667
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006668static int in_set_sample_rate(struct audio_stream *stream __unused,
6669 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006670{
6671 return -ENOSYS;
6672}
6673
6674static size_t in_get_buffer_size(const struct audio_stream *stream)
6675{
6676 struct stream_in *in = (struct stream_in *)stream;
6677
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006678 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6679 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006680 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6681 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306682 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306683 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006684
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006685 return in->config.period_size * in->af_period_multiplier *
6686 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006687}
6688
6689static uint32_t in_get_channels(const struct audio_stream *stream)
6690{
6691 struct stream_in *in = (struct stream_in *)stream;
6692
6693 return in->channel_mask;
6694}
6695
6696static audio_format_t in_get_format(const struct audio_stream *stream)
6697{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006698 struct stream_in *in = (struct stream_in *)stream;
6699
6700 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006701}
6702
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006703static int in_set_format(struct audio_stream *stream __unused,
6704 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006705{
6706 return -ENOSYS;
6707}
6708
6709static int in_standby(struct audio_stream *stream)
6710{
6711 struct stream_in *in = (struct stream_in *)stream;
6712 struct audio_device *adev = in->dev;
6713 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306714 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6715 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006716 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306717
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006718 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006719 if (!in->standby && in->is_st_session) {
6720 ALOGD("%s: sound trigger pcm stop lab", __func__);
6721 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006722 if (adev->num_va_sessions > 0)
6723 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006724 in->standby = 1;
6725 }
6726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006727 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006728 if (adev->adm_deregister_stream)
6729 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6730
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006731 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006732 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006733 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006734 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006735 voice_extn_compress_voip_close_input_stream(stream);
6736 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006737 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6738 do_stop = in->capture_started;
6739 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006740 if (in->mmap_shared_memory_fd >= 0) {
6741 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6742 __func__, in->mmap_shared_memory_fd);
6743 close(in->mmap_shared_memory_fd);
6744 in->mmap_shared_memory_fd = -1;
6745 }
Zhou Songa8895042016-07-05 17:54:22 +08006746 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306747 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306748 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006749 }
6750
Arun Mirpuri5d170872019-03-26 13:21:31 -07006751 if (in->pcm) {
6752 ATRACE_BEGIN("pcm_in_close");
6753 pcm_close(in->pcm);
6754 ATRACE_END();
6755 in->pcm = NULL;
6756 }
6757
Carter Hsu2e429db2019-05-14 18:50:52 +08006758 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006759 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006760
George Gao3018ede2019-10-23 13:23:00 -07006761 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6762 if (adev->num_va_sessions > 0)
6763 adev->num_va_sessions--;
6764 }
Quinn Malef6050362019-01-30 15:55:40 -08006765
Eric Laurent150dbfe2013-02-27 14:31:02 -08006766 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006767 }
6768 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006769 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006770 return status;
6771}
6772
Aalique Grahame22e49102018-12-18 14:23:57 -08006773static int in_dump(const struct audio_stream *stream,
6774 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006775{
Aalique Grahame22e49102018-12-18 14:23:57 -08006776 struct stream_in *in = (struct stream_in *)stream;
6777
6778 // We try to get the lock for consistency,
6779 // but it isn't necessary for these variables.
6780 // If we're not in standby, we may be blocked on a read.
6781 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6782 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6783 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6784 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6785
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006786 char buffer[256]; // for statistics formatting
6787 if (in->start_latency_ms.n > 0) {
6788 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6789 dprintf(fd, " Start latency ms: %s\n", buffer);
6790 }
6791
Aalique Grahame22e49102018-12-18 14:23:57 -08006792 if (locked) {
6793 pthread_mutex_unlock(&in->lock);
6794 }
6795
6796 // dump error info
6797 (void)error_log_dump(
6798 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006800 return 0;
6801}
6802
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306803static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6804{
6805 if (!stream || !parms)
6806 return;
6807
6808 struct stream_in *in = (struct stream_in *)stream;
6809 struct audio_device *adev = in->dev;
6810
6811 card_status_t status;
6812 int card;
6813 if (parse_snd_card_status(parms, &card, &status) < 0)
6814 return;
6815
6816 pthread_mutex_lock(&adev->lock);
6817 bool valid_cb = (card == adev->snd_card);
6818 pthread_mutex_unlock(&adev->lock);
6819
6820 if (!valid_cb)
6821 return;
6822
6823 lock_input_stream(in);
6824 if (in->card_status != status)
6825 in->card_status = status;
6826 pthread_mutex_unlock(&in->lock);
6827
6828 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6829 use_case_table[in->usecase],
6830 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6831
6832 // a better solution would be to report error back to AF and let
6833 // it put the stream to standby
6834 if (status == CARD_STATUS_OFFLINE)
6835 in_standby(&in->stream.common);
6836
6837 return;
6838}
6839
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006840int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006841 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006842 audio_source_t source)
6843{
6844 struct audio_device *adev = in->dev;
6845 int ret = 0;
6846
6847 lock_input_stream(in);
6848 pthread_mutex_lock(&adev->lock);
6849
6850 /* no audio source uses val == 0 */
6851 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6852 in->source = source;
6853 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6854 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6855 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6856 (in->config.rate == 8000 || in->config.rate == 16000 ||
6857 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6858 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6859 ret = voice_extn_compress_voip_open_input_stream(in);
6860 if (ret != 0) {
6861 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6862 __func__, ret);
6863 }
6864 }
6865 }
6866
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006867 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6868 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006869 // Workaround: If routing to an non existing usb device, fail gracefully
6870 // The routing request will otherwise block during 10 second
6871 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006872 struct str_parms *usb_addr =
6873 str_parms_create_str(get_usb_device_address(devices));
6874 if (is_usb_in_device_type(devices) && usb_addr &&
6875 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006876 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6877 ret = -ENOSYS;
6878 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006879 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006880 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006881 if (!in->standby && !in->is_st_session) {
6882 ALOGV("update input routing change");
6883 // inform adm before actual routing to prevent glitches.
6884 if (adev->adm_on_routing_change) {
6885 adev->adm_on_routing_change(adev->adm_data,
6886 in->capture_handle);
6887 ret = select_devices(adev, in->usecase);
6888 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6889 adev->adm_routing_changed = true;
6890 }
6891 }
6892 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006893 if (usb_addr)
6894 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006895 }
6896 pthread_mutex_unlock(&adev->lock);
6897 pthread_mutex_unlock(&in->lock);
6898
6899 ALOGD("%s: exit: status(%d)", __func__, ret);
6900 return ret;
6901}
6902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006903static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6904{
6905 struct stream_in *in = (struct stream_in *)stream;
6906 struct audio_device *adev = in->dev;
6907 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006908 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306909 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006910
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306911 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006912 parms = str_parms_create_str(kvpairs);
6913
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306914 if (!parms)
6915 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006916 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006917 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006918
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306919 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6920 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306921 strlcpy(in->profile, value, sizeof(in->profile));
6922 ALOGV("updating stream profile with value '%s'", in->profile);
6923 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6924 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006925 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306926 in->sample_rate, in->bit_width,
6927 in->profile, &in->app_type_cfg);
6928 }
6929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006930 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006931 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006932
6933 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306934error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306935 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006936}
6937
6938static char* in_get_parameters(const struct audio_stream *stream,
6939 const char *keys)
6940{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006941 struct stream_in *in = (struct stream_in *)stream;
6942 struct str_parms *query = str_parms_create_str(keys);
6943 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006944 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006945
6946 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006947 if (reply) {
6948 str_parms_destroy(reply);
6949 }
6950 if (query) {
6951 str_parms_destroy(query);
6952 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006953 ALOGE("in_get_parameters: failed to create query or reply");
6954 return NULL;
6955 }
6956
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006957 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006958
6959 voice_extn_in_get_parameters(in, query, reply);
6960
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006961 stream_get_parameter_channels(query, reply,
6962 &in->supported_channel_masks[0]);
6963 stream_get_parameter_formats(query, reply,
6964 &in->supported_formats[0]);
6965 stream_get_parameter_rates(query, reply,
6966 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006967 str = str_parms_to_str(reply);
6968 str_parms_destroy(query);
6969 str_parms_destroy(reply);
6970
6971 ALOGV("%s: exit: returns - %s", __func__, str);
6972 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006973}
6974
Aalique Grahame22e49102018-12-18 14:23:57 -08006975static int in_set_gain(struct audio_stream_in *stream,
6976 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006977{
Aalique Grahame22e49102018-12-18 14:23:57 -08006978 struct stream_in *in = (struct stream_in *)stream;
6979 char mixer_ctl_name[128];
6980 struct mixer_ctl *ctl;
6981 int ctl_value;
6982
6983 ALOGV("%s: gain %f", __func__, gain);
6984
6985 if (stream == NULL)
6986 return -EINVAL;
6987
6988 /* in_set_gain() only used to silence MMAP capture for now */
6989 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6990 return -ENOSYS;
6991
6992 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6993
6994 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6995 if (!ctl) {
6996 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6997 __func__, mixer_ctl_name);
6998 return -ENOSYS;
6999 }
7000
7001 if (gain < RECORD_GAIN_MIN)
7002 gain = RECORD_GAIN_MIN;
7003 else if (gain > RECORD_GAIN_MAX)
7004 gain = RECORD_GAIN_MAX;
7005 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
7006
7007 mixer_ctl_set_value(ctl, 0, ctl_value);
7008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007009 return 0;
7010}
7011
7012static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
7013 size_t bytes)
7014{
7015 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05307016
7017 if (in == NULL) {
7018 ALOGE("%s: stream_in ptr is NULL", __func__);
7019 return -EINVAL;
7020 }
7021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007022 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307023 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307024 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007025
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007026 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05307027
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007028 if (in->is_st_session) {
7029 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
7030 /* Read from sound trigger HAL */
7031 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08007032 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07007033 if (adev->num_va_sessions < UINT_MAX)
7034 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08007035 in->standby = 0;
7036 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007037 pthread_mutex_unlock(&in->lock);
7038 return bytes;
7039 }
7040
Haynes Mathew George16081042017-05-31 17:16:49 -07007041 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
7042 ret = -ENOSYS;
7043 goto exit;
7044 }
7045
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007046 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
7047 !in->standby && adev->adm_routing_changed) {
7048 ret = -ENOSYS;
7049 goto exit;
7050 }
7051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007052 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007053 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
7054
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007055 pthread_mutex_lock(&adev->lock);
7056 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
7057 ret = voice_extn_compress_voip_start_input_stream(in);
7058 else
7059 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07007060 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
7061 if (adev->num_va_sessions < UINT_MAX)
7062 adev->num_va_sessions++;
7063 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007064 pthread_mutex_unlock(&adev->lock);
7065 if (ret != 0) {
7066 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007067 }
7068 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07007069
7070 // log startup time in ms.
7071 simple_stats_log(
7072 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007073 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007074
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05307075 /* Avoid read if capture_stopped is set */
7076 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
7077 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
7078 ret = -EINVAL;
7079 goto exit;
7080 }
7081
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007082 // what's the duration requested by the client?
7083 long ns = 0;
7084
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307085 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007086 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7087 in->config.rate;
7088
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007089 ret = request_in_focus(in, ns);
7090 if (ret != 0)
7091 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007092 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007093
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307094 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307095 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7096 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307097 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007098 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307099 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007100 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007101 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007102 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007103 } else if (audio_extn_ffv_get_stream() == in) {
7104 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307105 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007106 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307107 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7108 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7109 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7110 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307111 ret = -EINVAL;
7112 goto exit;
7113 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307114 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307115 ret = -errno;
7116 }
7117 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307118 /* bytes read is always set to bytes for non compress usecases */
7119 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007120 }
7121
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007122 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007124 /*
Quinn Malef6050362019-01-30 15:55:40 -08007125 * Instead of writing zeroes here, we could trust the hardware to always
7126 * provide zeroes when muted. This is also muted with voice recognition
7127 * usecases so that other clients do not have access to voice recognition
7128 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007129 */
Quinn Malef6050362019-01-30 15:55:40 -08007130 if ((ret == 0 && voice_get_mic_mute(adev) &&
7131 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08007132 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
7133 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08007134 (adev->num_va_sessions &&
7135 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7136 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7137 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007138 memset(buffer, 0, bytes);
7139
7140exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307141 frame_size = audio_stream_in_frame_size(stream);
7142 if (frame_size > 0)
7143 in->frames_read += bytes_read/frame_size;
7144
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007145 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307146 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007147 pthread_mutex_unlock(&in->lock);
7148
7149 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307150 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307151 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307152 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307153 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307154 in->standby = true;
7155 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307156 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307157 bytes_read = bytes;
7158 memset(buffer, 0, bytes);
7159 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007160 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007161 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7162 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007163 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307164 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307165 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007166 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307167 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007168}
7169
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007170static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007171{
7172 return 0;
7173}
7174
Aalique Grahame22e49102018-12-18 14:23:57 -08007175static int in_get_capture_position(const struct audio_stream_in *stream,
7176 int64_t *frames, int64_t *time)
7177{
7178 if (stream == NULL || frames == NULL || time == NULL) {
7179 return -EINVAL;
7180 }
7181 struct stream_in *in = (struct stream_in *)stream;
7182 int ret = -ENOSYS;
7183
7184 lock_input_stream(in);
7185 // note: ST sessions do not close the alsa pcm driver synchronously
7186 // on standby. Therefore, we may return an error even though the
7187 // pcm stream is still opened.
7188 if (in->standby) {
7189 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7190 "%s stream in standby but pcm not NULL for non ST session", __func__);
7191 goto exit;
7192 }
7193 if (in->pcm) {
7194 struct timespec timestamp;
7195 unsigned int avail;
7196 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7197 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007198 pthread_mutex_lock(&adev->lock);
7199 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
7200 - platform_capture_latency(in->dev, in->usecase) * 1000LL;
7201 pthread_mutex_unlock(&adev->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08007202 ret = 0;
7203 }
7204 }
7205exit:
7206 pthread_mutex_unlock(&in->lock);
7207 return ret;
7208}
7209
Carter Hsu2e429db2019-05-14 18:50:52 +08007210static int in_update_effect_list(bool add, effect_handle_t effect,
7211 struct listnode *head)
7212{
7213 struct listnode *node;
7214 struct in_effect_list *elist = NULL;
7215 struct in_effect_list *target = NULL;
7216 int ret = 0;
7217
7218 if (!head)
7219 return ret;
7220
7221 list_for_each(node, head) {
7222 elist = node_to_item(node, struct in_effect_list, list);
7223 if (elist->handle == effect) {
7224 target = elist;
7225 break;
7226 }
7227 }
7228
7229 if (add) {
7230 if (target) {
7231 ALOGD("effect %p already exist", effect);
7232 return ret;
7233 }
7234
7235 target = (struct in_effect_list *)
7236 calloc(1, sizeof(struct in_effect_list));
7237
7238 if (!target) {
7239 ALOGE("%s:fail to allocate memory", __func__);
7240 return -ENOMEM;
7241 }
7242
7243 target->handle = effect;
7244 list_add_tail(head, &target->list);
7245 } else {
7246 if (target) {
7247 list_remove(&target->list);
7248 free(target);
7249 }
7250 }
7251
7252 return ret;
7253}
7254
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007255static int add_remove_audio_effect(const struct audio_stream *stream,
7256 effect_handle_t effect,
7257 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007258{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007259 struct stream_in *in = (struct stream_in *)stream;
7260 int status = 0;
7261 effect_descriptor_t desc;
7262
7263 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007264 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7265
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007266 if (status != 0)
7267 return status;
7268
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007269 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007270 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007271 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007272 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7273 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007274 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007275
7276 in_update_effect_list(enable, effect, &in->aec_list);
7277 enable = !list_empty(&in->aec_list);
7278 if (enable == in->enable_aec)
7279 goto exit;
7280
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007281 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007282 ALOGD("AEC enable %d", enable);
7283
Aalique Grahame22e49102018-12-18 14:23:57 -08007284 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7285 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7286 in->dev->enable_voicerx = enable;
7287 struct audio_usecase *usecase;
7288 struct listnode *node;
7289 list_for_each(node, &in->dev->usecase_list) {
7290 usecase = node_to_item(node, struct audio_usecase, list);
7291 if (usecase->type == PCM_PLAYBACK)
7292 select_devices(in->dev, usecase->id);
7293 }
7294 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007295 if (!in->standby) {
7296 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7297 select_devices(in->dev, in->usecase);
7298 }
7299
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007300 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007301 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7302
7303 in_update_effect_list(enable, effect, &in->ns_list);
7304 enable = !list_empty(&in->ns_list);
7305 if (enable == in->enable_ns)
7306 goto exit;
7307
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007308 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007309 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007310 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007311 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7312 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007313 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7314 select_devices(in->dev, in->usecase);
7315 } else
7316 select_devices(in->dev, in->usecase);
7317 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007318 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007319exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007320 pthread_mutex_unlock(&in->dev->lock);
7321 pthread_mutex_unlock(&in->lock);
7322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007323 return 0;
7324}
7325
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007326static int in_add_audio_effect(const struct audio_stream *stream,
7327 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007328{
Eric Laurent994a6932013-07-17 11:51:42 -07007329 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007330 return add_remove_audio_effect(stream, effect, true);
7331}
7332
7333static int in_remove_audio_effect(const struct audio_stream *stream,
7334 effect_handle_t effect)
7335{
Eric Laurent994a6932013-07-17 11:51:42 -07007336 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007337 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007338}
7339
Derek Chenf939fb72018-11-13 13:34:41 -08007340streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7341 audio_io_handle_t input)
7342{
7343 struct listnode *node;
7344
7345 list_for_each(node, &dev->active_inputs_list) {
7346 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7347 streams_input_ctxt_t,
7348 list);
7349 if (in_ctxt->input->capture_handle == input) {
7350 return in_ctxt;
7351 }
7352 }
7353 return NULL;
7354}
7355
7356streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7357 audio_io_handle_t output)
7358{
7359 struct listnode *node;
7360
7361 list_for_each(node, &dev->active_outputs_list) {
7362 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7363 streams_output_ctxt_t,
7364 list);
7365 if (out_ctxt->output->handle == output) {
7366 return out_ctxt;
7367 }
7368 }
7369 return NULL;
7370}
7371
Haynes Mathew George16081042017-05-31 17:16:49 -07007372static int in_stop(const struct audio_stream_in* stream)
7373{
7374 struct stream_in *in = (struct stream_in *)stream;
7375 struct audio_device *adev = in->dev;
7376
7377 int ret = -ENOSYS;
7378 ALOGV("%s", __func__);
7379 pthread_mutex_lock(&adev->lock);
7380 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7381 in->capture_started && in->pcm != NULL) {
7382 pcm_stop(in->pcm);
7383 ret = stop_input_stream(in);
7384 in->capture_started = false;
7385 }
7386 pthread_mutex_unlock(&adev->lock);
7387 return ret;
7388}
7389
7390static int in_start(const struct audio_stream_in* stream)
7391{
7392 struct stream_in *in = (struct stream_in *)stream;
7393 struct audio_device *adev = in->dev;
7394 int ret = -ENOSYS;
7395
7396 ALOGV("%s in %p", __func__, in);
7397 pthread_mutex_lock(&adev->lock);
7398 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7399 !in->capture_started && in->pcm != NULL) {
7400 if (!in->capture_started) {
7401 ret = start_input_stream(in);
7402 if (ret == 0) {
7403 in->capture_started = true;
7404 }
7405 }
7406 }
7407 pthread_mutex_unlock(&adev->lock);
7408 return ret;
7409}
7410
Phil Burke0a86d12019-02-16 22:28:11 -08007411// Read offset for the positional timestamp from a persistent vendor property.
7412// This is to workaround apparent inaccuracies in the timing information that
7413// is used by the AAudio timing model. The inaccuracies can cause glitches.
7414static int64_t in_get_mmap_time_offset() {
7415 const int32_t kDefaultOffsetMicros = 0;
7416 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007417 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007418 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7419 return mmap_time_offset_micros * (int64_t)1000;
7420}
7421
Haynes Mathew George16081042017-05-31 17:16:49 -07007422static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7423 int32_t min_size_frames,
7424 struct audio_mmap_buffer_info *info)
7425{
7426 struct stream_in *in = (struct stream_in *)stream;
7427 struct audio_device *adev = in->dev;
7428 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007429 unsigned int offset1 = 0;
7430 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007431 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007432 uint32_t mmap_size = 0;
7433 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007434
7435 pthread_mutex_lock(&adev->lock);
7436 ALOGV("%s in %p", __func__, in);
7437
Sharad Sanglec6f32552018-05-04 16:15:38 +05307438 if (CARD_STATUS_OFFLINE == in->card_status||
7439 CARD_STATUS_OFFLINE == adev->card_status) {
7440 ALOGW("in->card_status or adev->card_status offline, try again");
7441 ret = -EIO;
7442 goto exit;
7443 }
7444
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307445 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007446 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7447 ret = -EINVAL;
7448 goto exit;
7449 }
7450 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7451 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7452 ALOGV("%s in %p", __func__, in);
7453 ret = -ENOSYS;
7454 goto exit;
7455 }
7456 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7457 if (in->pcm_device_id < 0) {
7458 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7459 __func__, in->pcm_device_id, in->usecase);
7460 ret = -EINVAL;
7461 goto exit;
7462 }
7463
7464 adjust_mmap_period_count(&in->config, min_size_frames);
7465
7466 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7467 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7468 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7469 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307470 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307471 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7472 in->card_status = CARD_STATUS_OFFLINE;
7473 adev->card_status = CARD_STATUS_OFFLINE;
7474 ret = -EIO;
7475 goto exit;
7476 }
7477
Haynes Mathew George16081042017-05-31 17:16:49 -07007478 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7479 step = "open";
7480 ret = -ENODEV;
7481 goto exit;
7482 }
7483
7484 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7485 if (ret < 0) {
7486 step = "begin";
7487 goto exit;
7488 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007489
juyuchen626833d2019-06-04 16:48:02 +08007490 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007491 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7492 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7493 info->burst_size_frames = in->config.period_size;
7494 ret = platform_get_mmap_data_fd(adev->platform,
7495 in->pcm_device_id, 1 /*capture*/,
7496 &info->shared_memory_fd,
7497 &mmap_size);
7498 if (ret < 0) {
7499 // Fall back to non exclusive mode
7500 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7501 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007502 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7503 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7504
Arun Mirpuri5d170872019-03-26 13:21:31 -07007505 if (mmap_size < buffer_size) {
7506 step = "mmap";
7507 goto exit;
7508 }
juyuchen626833d2019-06-04 16:48:02 +08007509 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007510 }
7511
7512 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007513
7514 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7515 if (ret < 0) {
7516 step = "commit";
7517 goto exit;
7518 }
7519
Phil Burke0a86d12019-02-16 22:28:11 -08007520 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7521
Haynes Mathew George16081042017-05-31 17:16:49 -07007522 in->standby = false;
7523 ret = 0;
7524
7525 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7526 __func__, info->shared_memory_address, info->buffer_size_frames);
7527
7528exit:
7529 if (ret != 0) {
7530 if (in->pcm == NULL) {
7531 ALOGE("%s: %s - %d", __func__, step, ret);
7532 } else {
7533 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7534 pcm_close(in->pcm);
7535 in->pcm = NULL;
7536 }
7537 }
7538 pthread_mutex_unlock(&adev->lock);
7539 return ret;
7540}
7541
7542static int in_get_mmap_position(const struct audio_stream_in *stream,
7543 struct audio_mmap_position *position)
7544{
7545 struct stream_in *in = (struct stream_in *)stream;
7546 ALOGVV("%s", __func__);
7547 if (position == NULL) {
7548 return -EINVAL;
7549 }
7550 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7551 return -ENOSYS;
7552 }
7553 if (in->pcm == NULL) {
7554 return -ENOSYS;
7555 }
7556 struct timespec ts = { 0, 0 };
7557 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7558 if (ret < 0) {
7559 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7560 return ret;
7561 }
Phil Burke0a86d12019-02-16 22:28:11 -08007562 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7563 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007564 return 0;
7565}
7566
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307567static int in_get_active_microphones(const struct audio_stream_in *stream,
7568 struct audio_microphone_characteristic_t *mic_array,
7569 size_t *mic_count) {
7570 struct stream_in *in = (struct stream_in *)stream;
7571 struct audio_device *adev = in->dev;
7572 ALOGVV("%s", __func__);
7573
7574 lock_input_stream(in);
7575 pthread_mutex_lock(&adev->lock);
7576 int ret = platform_get_active_microphones(adev->platform,
7577 audio_channel_count_from_in_mask(in->channel_mask),
7578 in->usecase, mic_array, mic_count);
7579 pthread_mutex_unlock(&adev->lock);
7580 pthread_mutex_unlock(&in->lock);
7581
7582 return ret;
7583}
7584
7585static int adev_get_microphones(const struct audio_hw_device *dev,
7586 struct audio_microphone_characteristic_t *mic_array,
7587 size_t *mic_count) {
7588 struct audio_device *adev = (struct audio_device *)dev;
7589 ALOGVV("%s", __func__);
7590
7591 pthread_mutex_lock(&adev->lock);
7592 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7593 pthread_mutex_unlock(&adev->lock);
7594
7595 return ret;
7596}
juyuchendb308c22019-01-21 11:57:17 -07007597
7598static void in_update_sink_metadata(struct audio_stream_in *stream,
7599 const struct sink_metadata *sink_metadata) {
7600
7601 if (stream == NULL
7602 || sink_metadata == NULL
7603 || sink_metadata->tracks == NULL) {
7604 return;
7605 }
7606
7607 int error = 0;
7608 struct stream_in *in = (struct stream_in *)stream;
7609 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007610 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007611 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007612
7613 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007614
7615 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007616 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007617
7618 lock_input_stream(in);
7619 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007620 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007621
Zhou Song62ea0282020-03-22 19:53:01 +08007622 is_ha_usecase = adev->ha_proxy_enable ?
7623 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7624 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7625 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007626 && adev->voice_tx_output != NULL) {
7627 /* Use the rx device from afe-proxy record to route voice call because
7628 there is no routing if tx device is on primary hal and rx device
7629 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007630 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007631
7632 if (!voice_is_call_state_active(adev)) {
7633 if (adev->mode == AUDIO_MODE_IN_CALL) {
7634 adev->current_call_output = adev->voice_tx_output;
7635 error = voice_start_call(adev);
7636 if (error != 0)
7637 ALOGE("%s: start voice call failed %d", __func__, error);
7638 }
7639 } else {
7640 adev->current_call_output = adev->voice_tx_output;
7641 voice_update_devices_for_all_voice_usecases(adev);
7642 }
7643 }
7644
7645 pthread_mutex_unlock(&adev->lock);
7646 pthread_mutex_unlock(&in->lock);
7647}
7648
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307649int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007650 audio_io_handle_t handle,
7651 audio_devices_t devices,
7652 audio_output_flags_t flags,
7653 struct audio_config *config,
7654 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007655 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007656{
7657 struct audio_device *adev = (struct audio_device *)dev;
7658 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307659 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007660 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007661 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307662 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007663 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7664 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7665 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7666 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007667 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007668 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7669 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007670 bool force_haptic_path =
7671 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007672 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007673
kunleizdff872d2018-08-20 14:40:33 +08007674 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007675 is_usb_dev = false;
7676 devices = AUDIO_DEVICE_OUT_SPEAKER;
7677 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7678 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007679 if (config->format == AUDIO_FORMAT_DEFAULT)
7680 config->format = AUDIO_FORMAT_PCM_16_BIT;
7681 if (config->sample_rate == 0)
7682 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7683 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7684 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007685 }
7686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007687 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307688
Rahul Sharma99770982019-03-06 17:05:26 +05307689 pthread_mutex_lock(&adev->lock);
7690 if (out_get_stream(adev, handle) != NULL) {
7691 ALOGW("%s, output stream already opened", __func__);
7692 ret = -EEXIST;
7693 }
7694 pthread_mutex_unlock(&adev->lock);
7695 if (ret)
7696 return ret;
7697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007698 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7699
Mingming Yin3a941d42016-02-17 18:08:05 -08007700 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007701 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7702 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307703
7704
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007705 if (!out) {
7706 return -ENOMEM;
7707 }
7708
Haynes Mathew George204045b2015-02-25 20:32:03 -08007709 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007710 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307711 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007712 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007713 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007715 if (devices == AUDIO_DEVICE_NONE)
7716 devices = AUDIO_DEVICE_OUT_SPEAKER;
7717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007718 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007719 list_init(&out->device_list);
7720 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007721 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007722 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007723 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307724 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307725 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7726 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7727 else
7728 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007729 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007730 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007731 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307732 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307733 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307734 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007735 out->hal_output_suspend_supported = 0;
7736 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307737 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307738 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307739 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007740 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007741
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307742 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307743 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007744 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7745
Aalique Grahame22e49102018-12-18 14:23:57 -08007746 if (direct_dev &&
7747 (audio_is_linear_pcm(out->format) ||
7748 config->format == AUDIO_FORMAT_DEFAULT) &&
7749 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7750 audio_format_t req_format = config->format;
7751 audio_channel_mask_t req_channel_mask = config->channel_mask;
7752 uint32_t req_sample_rate = config->sample_rate;
7753
7754 pthread_mutex_lock(&adev->lock);
7755 if (is_hdmi) {
7756 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7757 ret = read_hdmi_sink_caps(out);
7758 if (config->sample_rate == 0)
7759 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7760 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7761 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7762 if (config->format == AUDIO_FORMAT_DEFAULT)
7763 config->format = AUDIO_FORMAT_PCM_16_BIT;
7764 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007765 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7766 &config->format,
7767 &out->supported_formats[0],
7768 MAX_SUPPORTED_FORMATS,
7769 &config->channel_mask,
7770 &out->supported_channel_masks[0],
7771 MAX_SUPPORTED_CHANNEL_MASKS,
7772 &config->sample_rate,
7773 &out->supported_sample_rates[0],
7774 MAX_SUPPORTED_SAMPLE_RATES);
7775 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007776 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007777
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007778 pthread_mutex_unlock(&adev->lock);
7779 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007780 if (ret == -ENOSYS) {
7781 /* ignore and go with default */
7782 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007783 }
7784 // For MMAP NO IRQ, allow conversions in ADSP
7785 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7786 goto error_open;
7787 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007788 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007789 goto error_open;
7790 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007791
7792 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7793 config->sample_rate = req_sample_rate;
7794 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7795 config->channel_mask = req_channel_mask;
7796 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7797 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007798 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007799
7800 out->sample_rate = config->sample_rate;
7801 out->channel_mask = config->channel_mask;
7802 out->format = config->format;
7803 if (is_hdmi) {
7804 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7805 out->config = pcm_config_hdmi_multi;
7806 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7807 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7808 out->config = pcm_config_mmap_playback;
7809 out->stream.start = out_start;
7810 out->stream.stop = out_stop;
7811 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7812 out->stream.get_mmap_position = out_get_mmap_position;
7813 } else {
7814 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7815 out->config = pcm_config_hifi;
7816 }
7817
7818 out->config.rate = out->sample_rate;
7819 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7820 if (is_hdmi) {
7821 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7822 audio_bytes_per_sample(out->format));
7823 }
7824 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007825 }
7826
Derek Chenf6318be2017-06-12 17:16:24 -04007827 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007828 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007829 /* extract car audio stream index */
7830 out->car_audio_stream =
7831 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7832 if (out->car_audio_stream < 0) {
7833 ALOGE("%s: invalid car audio stream %x",
7834 __func__, out->car_audio_stream);
7835 ret = -EINVAL;
7836 goto error_open;
7837 }
Derek Chen5f67a942020-02-24 23:08:13 -08007838 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007839 }
7840
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007841 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007842 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007843 if (!voice_extn_is_compress_voip_supported()) {
7844 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7845 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007846 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
Lakshman Chaluvarajue7fc9482020-05-30 14:29:29 +05307847 config->channel_mask : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007848 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7849 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007850 out->volume_l = INVALID_OUT_VOLUME;
7851 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007852
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007853 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007854 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007855 uint32_t channel_count =
7856 audio_channel_count_from_out_mask(out->channel_mask);
7857 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7858 out->sample_rate, out->format,
7859 channel_count, false);
7860 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7861 if (frame_size != 0)
7862 out->config.period_size = buffer_size / frame_size;
7863 else
7864 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007865 }
7866 } else {
7867 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7868 voice_extn_compress_voip_is_active(out->dev)) &&
7869 (voice_extn_compress_voip_is_config_supported(config))) {
7870 ret = voice_extn_compress_voip_open_output_stream(out);
7871 if (ret != 0) {
7872 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7873 __func__, ret);
7874 goto error_open;
7875 }
Sujin Panicker19027262019-09-16 18:28:06 +05307876 } else {
7877 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7878 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007879 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007880 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007881 } else if (audio_is_linear_pcm(out->format) &&
7882 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7883 out->channel_mask = config->channel_mask;
7884 out->sample_rate = config->sample_rate;
7885 out->format = config->format;
7886 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7887 // does this change?
7888 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7889 out->config.rate = config->sample_rate;
7890 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7891 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7892 audio_bytes_per_sample(config->format));
7893 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007894 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307895 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307896 pthread_mutex_lock(&adev->lock);
7897 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7898 pthread_mutex_unlock(&adev->lock);
7899
7900 // reject offload during card offline to allow
7901 // fallback to s/w paths
7902 if (offline) {
7903 ret = -ENODEV;
7904 goto error_open;
7905 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007906
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007907 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7908 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7909 ALOGE("%s: Unsupported Offload information", __func__);
7910 ret = -EINVAL;
7911 goto error_open;
7912 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007913
Atul Khare3fa6e542017-08-09 00:56:17 +05307914 if (config->offload_info.format == 0)
7915 config->offload_info.format = config->format;
7916 if (config->offload_info.sample_rate == 0)
7917 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007918
Mingming Yin90310102013-11-13 16:57:00 -08007919 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307920 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007921 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007922 ret = -EINVAL;
7923 goto error_open;
7924 }
7925
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007926 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7927 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7928 (audio_extn_passthru_is_passthrough_stream(out)) &&
7929 !((config->sample_rate == 48000) ||
7930 (config->sample_rate == 96000) ||
7931 (config->sample_rate == 192000))) {
7932 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7933 __func__, config->sample_rate, config->offload_info.format);
7934 ret = -EINVAL;
7935 goto error_open;
7936 }
7937
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007938 out->compr_config.codec = (struct snd_codec *)
7939 calloc(1, sizeof(struct snd_codec));
7940
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007941 if (!out->compr_config.codec) {
7942 ret = -ENOMEM;
7943 goto error_open;
7944 }
7945
Dhananjay Kumarac341582017-02-23 23:42:25 +05307946 out->stream.pause = out_pause;
7947 out->stream.resume = out_resume;
7948 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307949 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307950 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007951 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307952 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007953 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307954 } else {
7955 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7956 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007957 }
vivek mehta446c3962015-09-14 10:57:35 -07007958
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307959 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7960 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007961#ifdef AUDIO_GKI_ENABLED
7962 /* out->compr_config.codec->reserved[1] is for flags */
7963 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7964#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307965 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007966#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307967 }
7968
vivek mehta446c3962015-09-14 10:57:35 -07007969 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007970 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007971 config->format == 0 && config->sample_rate == 0 &&
7972 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007973 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007974 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7975 } else {
7976 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7977 ret = -EEXIST;
7978 goto error_open;
7979 }
vivek mehta446c3962015-09-14 10:57:35 -07007980 }
7981
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007982 if (config->offload_info.channel_mask)
7983 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007984 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007985 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007986 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007987 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307988 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007989 ret = -EINVAL;
7990 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007991 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007992
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007993 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007994 out->sample_rate = config->offload_info.sample_rate;
7995
Mingming Yin3ee55c62014-08-04 14:23:35 -07007996 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007997
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307998 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307999 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308000 audio_extn_dolby_send_ddp_endp_params(adev);
8001 audio_extn_dolby_set_dmid(adev);
8002 }
vivek mehta0ea887a2015-08-26 14:01:20 -07008003
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008004 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08008005 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008006 out->compr_config.codec->bit_rate =
8007 config->offload_info.bit_rate;
8008 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05308009 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008010 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05308011 /* Update bit width only for non passthrough usecases.
8012 * For passthrough usecases, the output will always be opened @16 bit
8013 */
8014 if (!audio_extn_passthru_is_passthrough_stream(out))
8015 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308016
8017 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08008018#ifdef AUDIO_GKI_ENABLED
8019 /* out->compr_config.codec->reserved[1] is for flags */
8020 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
8021 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
8022#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308023 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
8024 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08008025#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308026
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008027 /*TODO: Do we need to change it for passthrough */
8028 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008029
Manish Dewangana6fc5442015-08-24 20:30:31 +05308030 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
8031 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308032 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05308033 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05308034 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
8035 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308036
8037 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
8038 AUDIO_FORMAT_PCM) {
8039
8040 /*Based on platform support, configure appropriate alsa format for corresponding
8041 *hal input format.
8042 */
8043 out->compr_config.codec->format = hal_format_to_alsa(
8044 config->offload_info.format);
8045
Ashish Jain83a6cc22016-06-28 14:34:17 +05308046 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05308047 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308048 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308049
Dhananjay Kumarac341582017-02-23 23:42:25 +05308050 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05308051 *hal input format and alsa format might differ based on platform support.
8052 */
8053 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05308054 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05308055
8056 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
8057
Deeraj Soman93155a62019-09-30 19:00:37 +05308058 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
8059 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
8060 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
8061 out->info.duration_us = (int64_t)config->offload_info.duration_us;
8062 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05308063
Ashish Jainf1eaa582016-05-23 20:54:24 +05308064 /* Check if alsa session is configured with the same format as HAL input format,
8065 * if not then derive correct fragment size needed to accomodate the
8066 * conversion of HAL input format to alsa format.
8067 */
8068 audio_extn_utils_update_direct_pcm_fragment_size(out);
8069
8070 /*if hal input and output fragment size is different this indicates HAL input format is
8071 *not same as the alsa format
8072 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308073 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05308074 /*Allocate a buffer to convert input data to the alsa configured format.
8075 *size of convert buffer is equal to the size required to hold one fragment size
8076 *worth of pcm data, this is because flinger does not write more than fragment_size
8077 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05308078 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
8079 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05308080 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
8081 ret = -ENOMEM;
8082 goto error_open;
8083 }
8084 }
8085 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
8086 out->compr_config.fragment_size =
8087 audio_extn_passthru_get_buffer_size(&config->offload_info);
8088 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8089 } else {
8090 out->compr_config.fragment_size =
8091 platform_get_compress_offload_buffer_size(&config->offload_info);
8092 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8093 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008094
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308095 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8096 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8097 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07008098 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308099 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008100
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308101 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8102 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8103 }
8104
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008105 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8106 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008107
Manish Dewangan69426c82017-01-30 17:35:36 +05308108 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8109 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8110 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8111 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8112 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8113 } else {
8114 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8115 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008116
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308117 memset(&out->channel_map_param, 0,
8118 sizeof(struct audio_out_channel_map_param));
8119
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008120 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308121 out->send_next_track_params = false;
8122 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008123 out->offload_state = OFFLOAD_STATE_IDLE;
8124 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008125 out->writeAt.tv_sec = 0;
8126 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008127
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008128 audio_extn_dts_create_state_notifier_node(out->usecase);
8129
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008130 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8131 __func__, config->offload_info.version,
8132 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308133
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308134 /* Check if DSD audio format is supported in codec
8135 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308136 */
8137
8138 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308139 (!platform_check_codec_dsd_support(adev->platform) ||
8140 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308141 ret = -EINVAL;
8142 goto error_open;
8143 }
8144
Ashish Jain5106d362016-05-11 19:23:33 +05308145 /* Disable gapless if any of the following is true
8146 * passthrough playback
8147 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308148 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308149 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308150 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308151 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008152 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308153 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308154 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308155 check_and_set_gapless_mode(adev, false);
8156 } else
8157 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008158
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308159 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008160 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8161 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308162 if (config->format == AUDIO_FORMAT_DSD) {
8163 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008164#ifdef AUDIO_GKI_ENABLED
8165 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8166 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8167#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308168 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008169#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308170 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008171
8172 create_offload_callback_thread(out);
8173
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008174 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008175 switch (config->sample_rate) {
8176 case 0:
8177 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8178 break;
8179 case 8000:
8180 case 16000:
8181 case 48000:
8182 out->sample_rate = config->sample_rate;
8183 break;
8184 default:
8185 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8186 config->sample_rate);
8187 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8188 ret = -EINVAL;
8189 goto error_open;
8190 }
8191 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8192 switch (config->channel_mask) {
8193 case AUDIO_CHANNEL_NONE:
8194 case AUDIO_CHANNEL_OUT_STEREO:
8195 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8196 break;
8197 default:
8198 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8199 config->channel_mask);
8200 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8201 ret = -EINVAL;
8202 goto error_open;
8203 }
8204 switch (config->format) {
8205 case AUDIO_FORMAT_DEFAULT:
8206 case AUDIO_FORMAT_PCM_16_BIT:
8207 out->format = AUDIO_FORMAT_PCM_16_BIT;
8208 break;
8209 default:
8210 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8211 config->format);
8212 config->format = AUDIO_FORMAT_PCM_16_BIT;
8213 ret = -EINVAL;
8214 goto error_open;
8215 }
8216
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308217 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008218 if (ret != 0) {
8219 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008220 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008221 goto error_open;
8222 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008223 } else if (is_single_device_type_equal(&out->device_list,
8224 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008225 switch (config->sample_rate) {
8226 case 0:
8227 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8228 break;
8229 case 8000:
8230 case 16000:
8231 case 48000:
8232 out->sample_rate = config->sample_rate;
8233 break;
8234 default:
8235 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8236 config->sample_rate);
8237 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8238 ret = -EINVAL;
8239 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008240 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008241 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8242 switch (config->channel_mask) {
8243 case AUDIO_CHANNEL_NONE:
8244 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8245 break;
8246 case AUDIO_CHANNEL_OUT_STEREO:
8247 out->channel_mask = config->channel_mask;
8248 break;
8249 default:
8250 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8251 config->channel_mask);
8252 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8253 ret = -EINVAL;
8254 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008255 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008256 switch (config->format) {
8257 case AUDIO_FORMAT_DEFAULT:
8258 out->format = AUDIO_FORMAT_PCM_16_BIT;
8259 break;
8260 case AUDIO_FORMAT_PCM_16_BIT:
8261 out->format = config->format;
8262 break;
8263 default:
8264 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8265 config->format);
8266 config->format = AUDIO_FORMAT_PCM_16_BIT;
8267 ret = -EINVAL;
8268 break;
8269 }
8270 if (ret != 0)
8271 goto error_open;
8272
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008273 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8274 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008275 out->config.rate = out->sample_rate;
8276 out->config.channels =
8277 audio_channel_count_from_out_mask(out->channel_mask);
8278 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008279 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008280 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308281 unsigned int channels = 0;
8282 /*Update config params to default if not set by the caller*/
8283 if (config->sample_rate == 0)
8284 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8285 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8286 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8287 if (config->format == AUDIO_FORMAT_DEFAULT)
8288 config->format = AUDIO_FORMAT_PCM_16_BIT;
8289
8290 channels = audio_channel_count_from_out_mask(out->channel_mask);
8291
Varun Balaraje49253e2017-07-06 19:48:56 +05308292 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8293 out->usecase = get_interactive_usecase(adev);
8294 out->config = pcm_config_low_latency;
8295 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308296 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008297 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8298 out->flags);
8299 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008300 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8301 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8302 out->config = pcm_config_mmap_playback;
8303 out->stream.start = out_start;
8304 out->stream.stop = out_stop;
8305 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8306 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308307 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8308 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008309 out->hal_output_suspend_supported =
8310 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8311 out->dynamic_pm_qos_config_supported =
8312 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8313 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008314 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8315 } else {
8316 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8317 //the mixer path will be a string similar to "low-latency-playback resume"
8318 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8319 strlcat(out->pm_qos_mixer_path,
8320 " resume", MAX_MIXER_PATH_LEN);
8321 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8322 out->pm_qos_mixer_path);
8323 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308324 out->config = pcm_config_low_latency;
8325 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8326 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8327 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308328 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8329 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8330 if (out->config.period_size <= 0) {
8331 ALOGE("Invalid configuration period size is not valid");
8332 ret = -EINVAL;
8333 goto error_open;
8334 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008335 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8336 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8337 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008338 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8339 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8340 out->config = pcm_config_haptics_audio;
8341 if (force_haptic_path)
8342 adev->haptics_config = pcm_config_haptics_audio;
8343 else
8344 adev->haptics_config = pcm_config_haptics;
8345
Meng Wangd08ce322020-04-02 08:59:20 +08008346 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008347 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8348
8349 if (force_haptic_path) {
8350 out->config.channels = 1;
8351 adev->haptics_config.channels = 1;
8352 } else
8353 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 -08008354 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008355 ret = audio_extn_auto_hal_open_output_stream(out);
8356 if (ret) {
8357 ALOGE("%s: Failed to open output stream for bus device", __func__);
8358 ret = -EINVAL;
8359 goto error_open;
8360 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308361 } else {
8362 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008363 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8364 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308365 }
8366 out->hal_ip_format = format = out->format;
8367 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8368 out->hal_op_format = pcm_format_to_hal(out->config.format);
8369 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8370 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008371 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308372 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308373 if (out->hal_ip_format != out->hal_op_format) {
8374 uint32_t buffer_size = out->config.period_size *
8375 format_to_bitwidth_table[out->hal_op_format] *
8376 out->config.channels;
8377 out->convert_buffer = calloc(1, buffer_size);
8378 if (out->convert_buffer == NULL){
8379 ALOGE("Allocation failed for convert buffer for size %d",
8380 out->compr_config.fragment_size);
8381 ret = -ENOMEM;
8382 goto error_open;
8383 }
8384 ALOGD("Convert buffer allocated of size %d", buffer_size);
8385 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008386 }
8387
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008388 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8389 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308390
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008391 /* TODO remove this hardcoding and check why width is zero*/
8392 if (out->bit_width == 0)
8393 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308394 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008395 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008396 &out->device_list, out->flags,
8397 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308398 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308399 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008400 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008401 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8402 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008403 if(adev->primary_output == NULL)
8404 adev->primary_output = out;
8405 else {
8406 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008407 ret = -EEXIST;
8408 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008409 }
8410 }
8411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008412 /* Check if this usecase is already existing */
8413 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008414 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8415 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008416 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008417 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008418 ret = -EEXIST;
8419 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008420 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008422 pthread_mutex_unlock(&adev->lock);
8423
8424 out->stream.common.get_sample_rate = out_get_sample_rate;
8425 out->stream.common.set_sample_rate = out_set_sample_rate;
8426 out->stream.common.get_buffer_size = out_get_buffer_size;
8427 out->stream.common.get_channels = out_get_channels;
8428 out->stream.common.get_format = out_get_format;
8429 out->stream.common.set_format = out_set_format;
8430 out->stream.common.standby = out_standby;
8431 out->stream.common.dump = out_dump;
8432 out->stream.common.set_parameters = out_set_parameters;
8433 out->stream.common.get_parameters = out_get_parameters;
8434 out->stream.common.add_audio_effect = out_add_audio_effect;
8435 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8436 out->stream.get_latency = out_get_latency;
8437 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008438#ifdef NO_AUDIO_OUT
8439 out->stream.write = out_write_for_no_output;
8440#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008441 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008442#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008443 out->stream.get_render_position = out_get_render_position;
8444 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008445 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008446
Haynes Mathew George16081042017-05-31 17:16:49 -07008447 if (out->realtime)
8448 out->af_period_multiplier = af_period_multiplier;
8449 else
8450 out->af_period_multiplier = 1;
8451
Andy Hunga1f48fa2019-07-01 18:14:53 -07008452 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008454 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008455 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008456 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008457
8458 config->format = out->stream.common.get_format(&out->stream.common);
8459 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8460 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308461 register_format(out->format, out->supported_formats);
8462 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8463 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008464
Aalique Grahame22e49102018-12-18 14:23:57 -08008465 out->error_log = error_log_create(
8466 ERROR_LOG_ENTRIES,
8467 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8468
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308469 /*
8470 By locking output stream before registering, we allow the callback
8471 to update stream's state only after stream's initial state is set to
8472 adev state.
8473 */
8474 lock_output_stream(out);
8475 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8476 pthread_mutex_lock(&adev->lock);
8477 out->card_status = adev->card_status;
8478 pthread_mutex_unlock(&adev->lock);
8479 pthread_mutex_unlock(&out->lock);
8480
Aalique Grahame22e49102018-12-18 14:23:57 -08008481 stream_app_type_cfg_init(&out->app_type_cfg);
8482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008483 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308484 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008485 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008486
8487 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8488 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8489 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008490 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308491 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008492 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008493 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308494 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8495 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008496 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8497 out->usecase, PCM_PLAYBACK);
8498 hdlr_stream_cfg.flags = out->flags;
8499 hdlr_stream_cfg.type = PCM_PLAYBACK;
8500 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8501 &hdlr_stream_cfg);
8502 if (ret) {
8503 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8504 out->adsp_hdlr_stream_handle = NULL;
8505 }
8506 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308507 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8508 is_direct_passthough, false);
8509 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8510 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008511 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008512 if (ret < 0) {
8513 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8514 out->ip_hdlr_handle = NULL;
8515 }
8516 }
Derek Chenf939fb72018-11-13 13:34:41 -08008517
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008518 ret = io_streams_map_insert(adev, &out->stream.common,
8519 out->handle, AUDIO_PATCH_HANDLE_NONE);
8520 if (ret != 0)
8521 goto error_open;
8522
Derek Chenf939fb72018-11-13 13:34:41 -08008523 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8524 calloc(1, sizeof(streams_output_ctxt_t));
8525 if (out_ctxt == NULL) {
8526 ALOGE("%s fail to allocate output ctxt", __func__);
8527 ret = -ENOMEM;
8528 goto error_open;
8529 }
8530 out_ctxt->output = out;
8531
8532 pthread_mutex_lock(&adev->lock);
8533 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8534 pthread_mutex_unlock(&adev->lock);
8535
Eric Laurent994a6932013-07-17 11:51:42 -07008536 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008537 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008538
8539error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308540 if (out->convert_buffer)
8541 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008542 free(out);
8543 *stream_out = NULL;
8544 ALOGD("%s: exit: ret %d", __func__, ret);
8545 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008546}
8547
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308548void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008549 struct audio_stream_out *stream)
8550{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008551 struct stream_out *out = (struct stream_out *)stream;
8552 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008553 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008554
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008555 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308556
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008557 io_streams_map_remove(adev, out->handle);
8558
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308559 // must deregister from sndmonitor first to prevent races
8560 // between the callback and close_stream
8561 audio_extn_snd_mon_unregister_listener(out);
8562
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008563 /* close adsp hdrl session before standby */
8564 if (out->adsp_hdlr_stream_handle) {
8565 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8566 if (ret)
8567 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8568 out->adsp_hdlr_stream_handle = NULL;
8569 }
8570
Manish Dewangan21a850a2017-08-14 12:03:55 +05308571 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008572 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8573 out->ip_hdlr_handle = NULL;
8574 }
8575
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008576 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308577 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008578 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308579 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308580 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008581 if(ret != 0)
8582 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8583 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008584 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008585 out_standby(&stream->common);
8586
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008587 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008588 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008589 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008590 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008591 if (out->compr_config.codec != NULL)
8592 free(out->compr_config.codec);
8593 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008594
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308595 out->a2dp_compress_mute = false;
8596
Varun Balaraje49253e2017-07-06 19:48:56 +05308597 if (is_interactive_usecase(out->usecase))
8598 free_interactive_usecase(adev, out->usecase);
8599
Ashish Jain83a6cc22016-06-28 14:34:17 +05308600 if (out->convert_buffer != NULL) {
8601 free(out->convert_buffer);
8602 out->convert_buffer = NULL;
8603 }
8604
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008605 if (adev->voice_tx_output == out)
8606 adev->voice_tx_output = NULL;
8607
Aalique Grahame22e49102018-12-18 14:23:57 -08008608 error_log_destroy(out->error_log);
8609 out->error_log = NULL;
8610
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308611 if (adev->primary_output == out)
8612 adev->primary_output = NULL;
8613
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008614 pthread_cond_destroy(&out->cond);
8615 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008616
8617 pthread_mutex_lock(&adev->lock);
8618 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8619 if (out_ctxt != NULL) {
8620 list_remove(&out_ctxt->list);
8621 free(out_ctxt);
8622 } else {
8623 ALOGW("%s, output stream already closed", __func__);
8624 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008625 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008626 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008627 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008628}
8629
8630static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8631{
8632 struct audio_device *adev = (struct audio_device *)dev;
8633 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008634 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008635 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008636 int ret;
8637 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008638 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008639 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008640 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008641
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008642 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008643 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008644
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308645 if (!parms)
8646 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308647
Derek Chen6f293672019-04-01 01:40:24 -07008648 /* notify adev and input/output streams on the snd card status */
8649 adev_snd_mon_cb((void *)adev, parms);
8650
8651 list_for_each(node, &adev->active_outputs_list) {
8652 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8653 streams_output_ctxt_t,
8654 list);
8655 out_snd_mon_cb((void *)out_ctxt->output, parms);
8656 }
8657
8658 list_for_each(node, &adev->active_inputs_list) {
8659 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8660 streams_input_ctxt_t,
8661 list);
8662 in_snd_mon_cb((void *)in_ctxt->input, parms);
8663 }
8664
Zhou Songd6d71752019-05-21 18:08:51 +08008665 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308666 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8667 if (ret >= 0) {
8668 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008669 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308670 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008671 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308672 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008673 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008674 }
8675 }
8676
8677 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8678 if (ret>=0) {
8679 if (!strncmp(value, "false", 5) &&
8680 audio_extn_a2dp_source_is_suspended()) {
8681 struct audio_usecase *usecase;
8682 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008683 list_for_each(node, &adev->usecase_list) {
8684 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008685 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008686 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008687 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008688 reassign_device_list(&usecase->stream.in->device_list,
8689 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008690 select_devices(adev, usecase->id);
8691 }
Zhou Songd6d71752019-05-21 18:08:51 +08008692 }
8693 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308694 }
8695
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008696 status = voice_set_parameters(adev, parms);
8697 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008698 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008699
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008700 status = platform_set_parameters(adev->platform, parms);
8701 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008702 goto done;
8703
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008704 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8705 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008706 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008707 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8708 adev->bluetooth_nrec = true;
8709 else
8710 adev->bluetooth_nrec = false;
8711 }
8712
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008713 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8714 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008715 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8716 adev->screen_off = false;
8717 else
8718 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008719 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008720 }
8721
Eric Laurent4b084132018-10-19 17:33:43 -07008722 ret = str_parms_get_int(parms, "rotation", &val);
8723 if (ret >= 0) {
8724 bool reverse_speakers = false;
8725 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8726 switch (val) {
8727 // FIXME: note that the code below assumes that the speakers are in the correct placement
8728 // relative to the user when the device is rotated 90deg from its default rotation. This
8729 // assumption is device-specific, not platform-specific like this code.
8730 case 270:
8731 reverse_speakers = true;
8732 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8733 break;
8734 case 0:
8735 case 180:
8736 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8737 break;
8738 case 90:
8739 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8740 break;
8741 default:
8742 ALOGE("%s: unexpected rotation of %d", __func__, val);
8743 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008744 }
Eric Laurent4b084132018-10-19 17:33:43 -07008745 if (status == 0) {
8746 // check and set swap
8747 // - check if orientation changed and speaker active
8748 // - set rotation and cache the rotation value
8749 adev->camera_orientation =
8750 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8751 if (!audio_extn_is_maxx_audio_enabled())
8752 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8753 }
8754 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008755
Mingming Yin514a8bc2014-07-29 15:22:21 -07008756 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8757 if (ret >= 0) {
8758 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8759 adev->bt_wb_speech_enabled = true;
8760 else
8761 adev->bt_wb_speech_enabled = false;
8762 }
8763
Zhou Song12c29502019-03-16 10:37:18 +08008764 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8765 if (ret >= 0) {
8766 val = atoi(value);
8767 adev->swb_speech_mode = val;
8768 }
8769
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008770 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8771 if (ret >= 0) {
8772 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308773 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008774 if (audio_is_output_device(val) &&
8775 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008776 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008777 platform_get_controller_stream_from_params(parms, &controller, &stream);
8778 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8779 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008780 if (ret < 0) {
8781 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308782 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008783 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008784 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308785 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008786 /*
8787 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8788 * Per AudioPolicyManager, USB device is higher priority than WFD.
8789 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8790 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8791 * starting voice call on USB
8792 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008793 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308794 if (ret >= 0)
8795 audio_extn_usb_add_device(device, atoi(value));
8796
Zhou Song6f862822017-11-06 17:27:57 +08008797 if (!audio_extn_usb_is_tunnel_supported()) {
8798 ALOGV("detected USB connect .. disable proxy");
8799 adev->allow_afe_proxy_usage = false;
8800 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008801 }
8802 }
8803
8804 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8805 if (ret >= 0) {
8806 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308807 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008808 /*
8809 * The HDMI / Displayport disconnect handling has been moved to
8810 * audio extension to ensure that its parameters are not
8811 * invalidated prior to updating sysfs of the disconnect event
8812 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8813 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308814 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008815 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308816 if (ret >= 0)
8817 audio_extn_usb_remove_device(device, atoi(value));
8818
Zhou Song6f862822017-11-06 17:27:57 +08008819 if (!audio_extn_usb_is_tunnel_supported()) {
8820 ALOGV("detected USB disconnect .. enable proxy");
8821 adev->allow_afe_proxy_usage = true;
8822 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008823 }
8824 }
8825
Aalique Grahame22e49102018-12-18 14:23:57 -08008826 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008827 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008828
8829 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008830 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308831 struct audio_usecase *usecase;
8832 struct listnode *node;
8833 list_for_each(node, &adev->usecase_list) {
8834 usecase = node_to_item(node, struct audio_usecase, list);
Weiyin Jiangff56ff32020-05-08 14:32:21 +08008835 if ((usecase->stream.out == NULL) || (usecase->type != PCM_PLAYBACK))
8836 continue;
8837
8838 if (is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308839 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008840 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308841 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008842 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308843 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308844 ALOGD("Switching to speaker and muting the stream before select_devices");
8845 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308846 //force device switch to re configure encoder
8847 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308848 ALOGD("Unmuting the stream after select_devices");
8849 usecase->stream.out->a2dp_compress_mute = false;
8850 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 +05308851 audio_extn_a2dp_set_handoff_mode(false);
8852 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308853 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308854 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8855 usecase->stream.out->a2dp_compress_mute) {
8856 pthread_mutex_unlock(&adev->lock);
8857 lock_output_stream(usecase->stream.out);
8858 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008859 reassign_device_list(&usecase->stream.out->device_list,
8860 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308861 check_a2dp_restore_l(adev, usecase->stream.out, true);
8862 pthread_mutex_unlock(&usecase->stream.out->lock);
8863 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308864 }
8865 }
8866 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008867
8868 //handle vr audio setparam
8869 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8870 value, sizeof(value));
8871 if (ret >= 0) {
8872 ALOGI("Setting vr mode to be %s", value);
8873 if (!strncmp(value, "true", 4)) {
8874 adev->vr_audio_mode_enabled = true;
8875 ALOGI("Setting vr mode to true");
8876 } else if (!strncmp(value, "false", 5)) {
8877 adev->vr_audio_mode_enabled = false;
8878 ALOGI("Setting vr mode to false");
8879 } else {
8880 ALOGI("wrong vr mode set");
8881 }
8882 }
8883
Eric Laurent4b084132018-10-19 17:33:43 -07008884 //FIXME: to be replaced by proper video capture properties API
8885 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8886 if (ret >= 0) {
8887 int camera_facing = CAMERA_FACING_BACK;
8888 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8889 camera_facing = CAMERA_FACING_FRONT;
8890 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8891 camera_facing = CAMERA_FACING_BACK;
8892 else {
8893 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8894 goto done;
8895 }
8896 adev->camera_orientation =
8897 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8898 struct audio_usecase *usecase;
8899 struct listnode *node;
8900 list_for_each(node, &adev->usecase_list) {
8901 usecase = node_to_item(node, struct audio_usecase, list);
8902 struct stream_in *in = usecase->stream.in;
8903 if (usecase->type == PCM_CAPTURE && in != NULL &&
8904 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8905 select_devices(adev, in->usecase);
8906 }
8907 }
8908 }
8909
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308910 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008911done:
8912 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008913 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308914error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008915 ALOGV("%s: exit with code(%d)", __func__, status);
8916 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008917}
8918
8919static char* adev_get_parameters(const struct audio_hw_device *dev,
8920 const char *keys)
8921{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308922 ALOGD("%s:%s", __func__, keys);
8923
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008924 struct audio_device *adev = (struct audio_device *)dev;
8925 struct str_parms *reply = str_parms_create();
8926 struct str_parms *query = str_parms_create_str(keys);
8927 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308928 char value[256] = {0};
8929 int ret = 0;
8930
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008931 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008932 if (reply) {
8933 str_parms_destroy(reply);
8934 }
8935 if (query) {
8936 str_parms_destroy(query);
8937 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008938 ALOGE("adev_get_parameters: failed to create query or reply");
8939 return NULL;
8940 }
8941
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008942 //handle vr audio getparam
8943
8944 ret = str_parms_get_str(query,
8945 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8946 value, sizeof(value));
8947
8948 if (ret >= 0) {
8949 bool vr_audio_enabled = false;
8950 pthread_mutex_lock(&adev->lock);
8951 vr_audio_enabled = adev->vr_audio_mode_enabled;
8952 pthread_mutex_unlock(&adev->lock);
8953
8954 ALOGI("getting vr mode to %d", vr_audio_enabled);
8955
8956 if (vr_audio_enabled) {
8957 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8958 "true");
8959 goto exit;
8960 } else {
8961 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8962 "false");
8963 goto exit;
8964 }
8965 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008966
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008967 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008968 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008969 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008970 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008971 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08008972 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308973 pthread_mutex_unlock(&adev->lock);
8974
Naresh Tannirud7205b62014-06-20 02:54:48 +05308975exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008976 str = str_parms_to_str(reply);
8977 str_parms_destroy(query);
8978 str_parms_destroy(reply);
8979
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308980 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008981 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008982}
8983
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008984static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008985{
8986 return 0;
8987}
8988
8989static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8990{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008991 int ret;
8992 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008993
8994 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8995
Haynes Mathew George5191a852013-09-11 14:19:36 -07008996 pthread_mutex_lock(&adev->lock);
8997 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008998 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008999 pthread_mutex_unlock(&adev->lock);
9000 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009001}
9002
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009003static int adev_set_master_volume(struct audio_hw_device *dev __unused,
9004 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009005{
9006 return -ENOSYS;
9007}
9008
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009009static int adev_get_master_volume(struct audio_hw_device *dev __unused,
9010 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009011{
9012 return -ENOSYS;
9013}
9014
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009015static int adev_set_master_mute(struct audio_hw_device *dev __unused,
9016 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009017{
9018 return -ENOSYS;
9019}
9020
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009021static int adev_get_master_mute(struct audio_hw_device *dev __unused,
9022 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009023{
9024 return -ENOSYS;
9025}
9026
9027static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
9028{
9029 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07009030 struct listnode *node;
9031 struct audio_usecase *usecase = NULL;
9032 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08009033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009034 pthread_mutex_lock(&adev->lock);
9035 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05309036 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
9037 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009038 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05309039 if( mode == AUDIO_MODE_CALL_SCREEN ){
9040 adev->current_call_output = adev->primary_output;
9041 voice_start_call(adev);
9042 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08009043 (mode == AUDIO_MODE_NORMAL ||
9044 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07009045 list_for_each(node, &adev->usecase_list) {
9046 usecase = node_to_item(node, struct audio_usecase, list);
9047 if (usecase->type == VOICE_CALL)
9048 break;
9049 }
9050 if (usecase &&
9051 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
9052 ret = audio_extn_usb_check_and_set_svc_int(usecase,
9053 true);
9054 if (ret != 0) {
9055 /* default service interval was successfully updated,
9056 reopen USB backend with new service interval */
9057 check_usecases_codec_backend(adev,
9058 usecase,
9059 usecase->out_snd_device);
9060 }
9061 }
9062
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009063 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07009064 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009065 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08009066 // restore device for other active usecases after stop call
9067 list_for_each(node, &adev->usecase_list) {
9068 usecase = node_to_item(node, struct audio_usecase, list);
9069 select_devices(adev, usecase->id);
9070 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009071 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009072 }
9073 pthread_mutex_unlock(&adev->lock);
9074 return 0;
9075}
9076
9077static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
9078{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009079 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08009080 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009081
9082 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08009083 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009084 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009085
Derek Chend2530072014-11-24 12:39:14 -08009086 if (adev->ext_hw_plugin)
9087 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08009088
9089 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08009090 pthread_mutex_unlock(&adev->lock);
9091
9092 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009093}
9094
9095static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9096{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009097 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009098 return 0;
9099}
9100
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009101static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009102 const struct audio_config *config)
9103{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009104 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009105
Aalique Grahame22e49102018-12-18 14:23:57 -08009106 /* Don't know if USB HIFI in this context so use true to be conservative */
9107 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9108 true /*is_usb_hifi */) != 0)
9109 return 0;
9110
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009111 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9112 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009113}
9114
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009115static bool adev_input_allow_hifi_record(struct audio_device *adev,
9116 audio_devices_t devices,
9117 audio_input_flags_t flags,
9118 audio_source_t source) {
9119 const bool allowed = true;
9120
9121 if (!audio_is_usb_in_device(devices))
9122 return !allowed;
9123
9124 switch (flags) {
9125 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009126 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009127 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9128 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009129 default:
9130 return !allowed;
9131 }
9132
9133 switch (source) {
9134 case AUDIO_SOURCE_DEFAULT:
9135 case AUDIO_SOURCE_MIC:
9136 case AUDIO_SOURCE_UNPROCESSED:
9137 break;
9138 default:
9139 return !allowed;
9140 }
9141
9142 switch (adev->mode) {
9143 case 0:
9144 break;
9145 default:
9146 return !allowed;
9147 }
9148
9149 return allowed;
9150}
9151
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009152static int adev_update_voice_comm_input_stream(struct stream_in *in,
9153 struct audio_config *config)
9154{
9155 bool valid_rate = (config->sample_rate == 8000 ||
9156 config->sample_rate == 16000 ||
9157 config->sample_rate == 32000 ||
9158 config->sample_rate == 48000);
9159 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9160
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009161 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009162 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009163 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9164 in->config = default_pcm_config_voip_copp;
9165 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9166 DEFAULT_VOIP_BUF_DURATION_MS,
9167 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009168 } else {
9169 ALOGW("%s No valid input in voip, use defaults"
9170 "sample rate %u, channel mask 0x%X",
9171 __func__, config->sample_rate, in->channel_mask);
9172 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009173 in->config.rate = config->sample_rate;
9174 in->sample_rate = config->sample_rate;
9175 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009176 //XXX needed for voice_extn_compress_voip_open_input_stream
9177 in->config.rate = config->sample_rate;
9178 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309179 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009180 voice_extn_compress_voip_is_active(in->dev)) &&
9181 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9182 valid_rate && valid_ch) {
9183 voice_extn_compress_voip_open_input_stream(in);
9184 // update rate entries to match config from AF
9185 in->config.rate = config->sample_rate;
9186 in->sample_rate = config->sample_rate;
9187 } else {
9188 ALOGW("%s compress voip not active, use defaults", __func__);
9189 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009190 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009191 return 0;
9192}
9193
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009194static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009195 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009196 audio_devices_t devices,
9197 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009198 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309199 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009200 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009201 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009202{
9203 struct audio_device *adev = (struct audio_device *)dev;
9204 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009205 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009206 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009207 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309208 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009209 bool is_usb_dev = audio_is_usb_in_device(devices);
9210 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9211 devices,
9212 flags,
9213 source);
Andy Hung94320602018-10-29 18:31:12 -07009214 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9215 " sample_rate %u, channel_mask %#x, format %#x",
9216 __func__, flags, is_usb_dev, may_use_hifi_record,
9217 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309218
kunleizdff872d2018-08-20 14:40:33 +08009219 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009220 is_usb_dev = false;
9221 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9222 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9223 __func__, devices);
9224 }
9225
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009226 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009227
9228 if (!(is_usb_dev && may_use_hifi_record)) {
9229 if (config->sample_rate == 0)
9230 config->sample_rate = 48000;
9231 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9232 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9233 if (config->format == AUDIO_FORMAT_DEFAULT)
9234 config->format = AUDIO_FORMAT_PCM_16_BIT;
9235
9236 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9237
Aalique Grahame22e49102018-12-18 14:23:57 -08009238 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9239 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009240 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309241 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009242
Rahul Sharma99770982019-03-06 17:05:26 +05309243 pthread_mutex_lock(&adev->lock);
9244 if (in_get_stream(adev, handle) != NULL) {
9245 ALOGW("%s, input stream already opened", __func__);
9246 ret = -EEXIST;
9247 }
9248 pthread_mutex_unlock(&adev->lock);
9249 if (ret)
9250 return ret;
9251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009252 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009253
9254 if (!in) {
9255 ALOGE("failed to allocate input stream");
9256 return -ENOMEM;
9257 }
9258
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309259 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309260 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9261 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009262 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009263 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009264
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009265 in->stream.common.get_sample_rate = in_get_sample_rate;
9266 in->stream.common.set_sample_rate = in_set_sample_rate;
9267 in->stream.common.get_buffer_size = in_get_buffer_size;
9268 in->stream.common.get_channels = in_get_channels;
9269 in->stream.common.get_format = in_get_format;
9270 in->stream.common.set_format = in_set_format;
9271 in->stream.common.standby = in_standby;
9272 in->stream.common.dump = in_dump;
9273 in->stream.common.set_parameters = in_set_parameters;
9274 in->stream.common.get_parameters = in_get_parameters;
9275 in->stream.common.add_audio_effect = in_add_audio_effect;
9276 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9277 in->stream.set_gain = in_set_gain;
9278 in->stream.read = in_read;
9279 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009280 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309281 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009282 in->stream.set_microphone_direction = in_set_microphone_direction;
9283 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009284 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009285
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009286 list_init(&in->device_list);
9287 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009288 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009289 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009290 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009291 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009292 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009293 in->bit_width = 16;
9294 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009295 in->direction = MIC_DIRECTION_UNSPECIFIED;
9296 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009297 list_init(&in->aec_list);
9298 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009299 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009300
Andy Hung94320602018-10-29 18:31:12 -07009301 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009302 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9303 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9304 /* Force channel config requested to mono if incall
9305 record is being requested for only uplink/downlink */
9306 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9307 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9308 ret = -EINVAL;
9309 goto err_open;
9310 }
9311 }
9312
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009313 if (is_usb_dev && may_use_hifi_record) {
9314 /* HiFi record selects an appropriate format, channel, rate combo
9315 depending on sink capabilities*/
9316 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9317 &config->format,
9318 &in->supported_formats[0],
9319 MAX_SUPPORTED_FORMATS,
9320 &config->channel_mask,
9321 &in->supported_channel_masks[0],
9322 MAX_SUPPORTED_CHANNEL_MASKS,
9323 &config->sample_rate,
9324 &in->supported_sample_rates[0],
9325 MAX_SUPPORTED_SAMPLE_RATES);
9326 if (ret != 0) {
9327 ret = -EINVAL;
9328 goto err_open;
9329 }
9330 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009331 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309332 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309333 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9334 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9335 in->config.format = PCM_FORMAT_S32_LE;
9336 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309337 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9338 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9339 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9340 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9341 bool ret_error = false;
9342 in->bit_width = 24;
9343 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9344 from HAL is 24_packed and 8_24
9345 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9346 24_packed return error indicating supported format is 24_packed
9347 *> In case of any other source requesting 24 bit or float return error
9348 indicating format supported is 16 bit only.
9349
9350 on error flinger will retry with supported format passed
9351 */
9352 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9353 (source != AUDIO_SOURCE_CAMCORDER)) {
9354 config->format = AUDIO_FORMAT_PCM_16_BIT;
9355 if (config->sample_rate > 48000)
9356 config->sample_rate = 48000;
9357 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009358 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9359 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309360 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9361 ret_error = true;
9362 }
9363
9364 if (ret_error) {
9365 ret = -EINVAL;
9366 goto err_open;
9367 }
9368 }
9369
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009370 in->channel_mask = config->channel_mask;
9371 in->format = config->format;
9372
9373 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309374
9375 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9376 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9377 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9378 else {
9379 ret = -EINVAL;
9380 goto err_open;
9381 }
9382 }
9383
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009384 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309385 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9386 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009387 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9388 is_low_latency = true;
9389#if LOW_LATENCY_CAPTURE_USE_CASE
9390 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9391#endif
9392 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009393 if (!in->realtime) {
9394 in->config = pcm_config_audio_capture;
9395 frame_size = audio_stream_in_frame_size(&in->stream);
9396 buffer_size = get_input_buffer_size(config->sample_rate,
9397 config->format,
9398 channel_count,
9399 is_low_latency);
9400 in->config.period_size = buffer_size / frame_size;
9401 in->config.rate = config->sample_rate;
9402 in->af_period_multiplier = 1;
9403 } else {
9404 // period size is left untouched for rt mode playback
9405 in->config = pcm_config_audio_capture_rt;
9406 in->af_period_multiplier = af_period_multiplier;
9407 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009408 }
9409
9410 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9411 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9412 in->realtime = 0;
9413 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9414 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009415 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009416 in->stream.start = in_start;
9417 in->stream.stop = in_stop;
9418 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9419 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009420 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009421 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009422 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9423 in->config = pcm_config_audio_capture;
9424 frame_size = audio_stream_in_frame_size(&in->stream);
9425 buffer_size = get_input_buffer_size(config->sample_rate,
9426 config->format,
9427 channel_count,
9428 false /*is_low_latency*/);
9429 in->config.period_size = buffer_size / frame_size;
9430 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009431 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009432 switch (config->format) {
9433 case AUDIO_FORMAT_PCM_32_BIT:
9434 in->bit_width = 32;
9435 break;
9436 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9437 case AUDIO_FORMAT_PCM_8_24_BIT:
9438 in->bit_width = 24;
9439 break;
9440 default:
9441 in->bit_width = 16;
9442 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009443 } else if (is_single_device_type_equal(&in->device_list,
9444 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9445 is_single_device_type_equal(&in->device_list,
9446 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009447 if (config->sample_rate == 0)
9448 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9449 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9450 config->sample_rate != 8000) {
9451 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9452 ret = -EINVAL;
9453 goto err_open;
9454 }
9455 if (config->format == AUDIO_FORMAT_DEFAULT)
9456 config->format = AUDIO_FORMAT_PCM_16_BIT;
9457 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9458 config->format = AUDIO_FORMAT_PCM_16_BIT;
9459 ret = -EINVAL;
9460 goto err_open;
9461 }
9462
9463 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009464 if (adev->ha_proxy_enable &&
9465 is_single_device_type_equal(&in->device_list,
9466 AUDIO_DEVICE_IN_TELEPHONY_RX))
9467 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009468 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009469 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009470 in->af_period_multiplier = 1;
9471 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9472 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9473 (config->sample_rate == 8000 ||
9474 config->sample_rate == 16000 ||
9475 config->sample_rate == 32000 ||
9476 config->sample_rate == 48000) &&
9477 channel_count == 1) {
9478 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9479 in->config = pcm_config_audio_capture;
9480 frame_size = audio_stream_in_frame_size(&in->stream);
9481 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9482 config->sample_rate,
9483 config->format,
9484 channel_count, false /*is_low_latency*/);
9485 in->config.period_size = buffer_size / frame_size;
9486 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9487 in->config.rate = config->sample_rate;
9488 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009489 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309490 int ret_val;
9491 pthread_mutex_lock(&adev->lock);
9492 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9493 in, config, &channel_mask_updated);
9494 pthread_mutex_unlock(&adev->lock);
9495
9496 if (!ret_val) {
9497 if (channel_mask_updated == true) {
9498 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9499 __func__, config->channel_mask);
9500 ret = -EINVAL;
9501 goto err_open;
9502 }
9503 ALOGD("%s: created multi-channel session succesfully",__func__);
9504 } else if (audio_extn_compr_cap_enabled() &&
9505 audio_extn_compr_cap_format_supported(config->format) &&
9506 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9507 audio_extn_compr_cap_init(in);
9508 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309509 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309510 if (ret)
9511 goto err_open;
9512 } else {
9513 in->config = pcm_config_audio_capture;
9514 in->config.rate = config->sample_rate;
9515 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309516 in->format = config->format;
9517 frame_size = audio_stream_in_frame_size(&in->stream);
9518 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009519 config->format,
9520 channel_count,
9521 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009522 /* prevent division-by-zero */
9523 if (frame_size == 0) {
9524 ALOGE("%s: Error frame_size==0", __func__);
9525 ret = -EINVAL;
9526 goto err_open;
9527 }
9528
Revathi Uddarajud2634032017-12-07 14:42:34 +05309529 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009530 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009531
Revathi Uddarajud2634032017-12-07 14:42:34 +05309532 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9533 /* optionally use VOIP usecase depending on config(s) */
9534 ret = adev_update_voice_comm_input_stream(in, config);
9535 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009536
Revathi Uddarajud2634032017-12-07 14:42:34 +05309537 if (ret) {
9538 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9539 goto err_open;
9540 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009541 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309542
9543 /* assign concurrent capture usecase if record has to caried out from
9544 * actual hardware input source */
9545 if (audio_extn_is_concurrent_capture_enabled() &&
9546 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309547 /* Acquire lock to avoid two concurrent use cases initialized to
9548 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009549
Samyak Jainc37062f2019-04-25 18:41:06 +05309550 if (in->usecase == USECASE_AUDIO_RECORD) {
9551 pthread_mutex_lock(&adev->lock);
9552 if (!(adev->pcm_record_uc_state)) {
9553 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9554 adev->pcm_record_uc_state = 1;
9555 pthread_mutex_unlock(&adev->lock);
9556 } else {
9557 pthread_mutex_unlock(&adev->lock);
9558 /* Assign compress record use case for second record */
9559 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9560 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9561 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9562 if (audio_extn_cin_applicable_stream(in)) {
9563 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309564 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309565 if (ret)
9566 goto err_open;
9567 }
9568 }
9569 }
kunleiz28c73e72019-03-27 17:24:04 +08009570 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009571 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309572 if (audio_extn_ssr_get_stream() != in)
9573 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009574
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009575 in->sample_rate = in->config.rate;
9576
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309577 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9578 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009579 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009580 in->sample_rate, in->bit_width,
9581 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309582 register_format(in->format, in->supported_formats);
9583 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9584 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309585
Aalique Grahame22e49102018-12-18 14:23:57 -08009586 in->error_log = error_log_create(
9587 ERROR_LOG_ENTRIES,
9588 1000000000 /* aggregate consecutive identical errors within one second */);
9589
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009590 /* This stream could be for sound trigger lab,
9591 get sound trigger pcm if present */
9592 audio_extn_sound_trigger_check_and_get_session(in);
9593
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309594 lock_input_stream(in);
9595 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9596 pthread_mutex_lock(&adev->lock);
9597 in->card_status = adev->card_status;
9598 pthread_mutex_unlock(&adev->lock);
9599 pthread_mutex_unlock(&in->lock);
9600
Aalique Grahame22e49102018-12-18 14:23:57 -08009601 stream_app_type_cfg_init(&in->app_type_cfg);
9602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009603 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009604
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009605 ret = io_streams_map_insert(adev, &in->stream.common,
9606 handle, AUDIO_PATCH_HANDLE_NONE);
9607 if (ret != 0)
9608 goto err_open;
9609
Derek Chenf939fb72018-11-13 13:34:41 -08009610 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9611 calloc(1, sizeof(streams_input_ctxt_t));
9612 if (in_ctxt == NULL) {
9613 ALOGE("%s fail to allocate input ctxt", __func__);
9614 ret = -ENOMEM;
9615 goto err_open;
9616 }
9617 in_ctxt->input = in;
9618
9619 pthread_mutex_lock(&adev->lock);
9620 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9621 pthread_mutex_unlock(&adev->lock);
9622
Eric Laurent994a6932013-07-17 11:51:42 -07009623 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009624 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009625
9626err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309627 if (in->usecase == USECASE_AUDIO_RECORD) {
9628 pthread_mutex_lock(&adev->lock);
9629 adev->pcm_record_uc_state = 0;
9630 pthread_mutex_unlock(&adev->lock);
9631 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009632 free(in);
9633 *stream_in = NULL;
9634 return ret;
9635}
9636
9637static void adev_close_input_stream(struct audio_hw_device *dev,
9638 struct audio_stream_in *stream)
9639{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009640 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009641 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009642 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309643
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309644 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009645
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009646 if (in == NULL) {
9647 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9648 return;
9649 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009650 io_streams_map_remove(adev, in->capture_handle);
9651
kunleiz70e57612018-12-28 17:50:23 +08009652 /* must deregister from sndmonitor first to prevent races
9653 * between the callback and close_stream
9654 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309655 audio_extn_snd_mon_unregister_listener(stream);
9656
kunleiz70e57612018-12-28 17:50:23 +08009657 /* Disable echo reference if there are no active input, hfp call
9658 * and sound trigger while closing input stream
9659 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009660 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009661 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009662 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9663 struct listnode out_devices;
9664 list_init(&out_devices);
9665 platform_set_echo_reference(adev, false, &out_devices);
9666 } else
kunleiz70e57612018-12-28 17:50:23 +08009667 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309668
Weiyin Jiang2995f662019-04-17 14:25:12 +08009669 error_log_destroy(in->error_log);
9670 in->error_log = NULL;
9671
Pallavid7c7a272018-01-16 11:22:55 +05309672
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009673 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309674 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009675 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309676 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009677 if (ret != 0)
9678 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9679 __func__, ret);
9680 } else
9681 in_standby(&stream->common);
9682
Revathi Uddarajud2634032017-12-07 14:42:34 +05309683 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309684 if (in->usecase == USECASE_AUDIO_RECORD) {
9685 adev->pcm_record_uc_state = 0;
9686 }
9687
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009688 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9689 adev->enable_voicerx = false;
9690 }
9691
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009692 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009693 audio_extn_ssr_deinit();
9694 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009695
Garmond Leunge2433c32017-09-28 21:51:22 -07009696 if (audio_extn_ffv_get_stream() == in) {
9697 audio_extn_ffv_stream_deinit();
9698 }
9699
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309700 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009701 audio_extn_compr_cap_format_supported(in->config.format))
9702 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309703
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309704 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309705 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009706
Mingming Yinfd7607b2016-01-22 12:48:44 -08009707 if (in->is_st_session) {
9708 ALOGV("%s: sound trigger pcm stop lab", __func__);
9709 audio_extn_sound_trigger_stop_lab(in);
9710 }
Derek Chenf939fb72018-11-13 13:34:41 -08009711 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9712 if (in_ctxt != NULL) {
9713 list_remove(&in_ctxt->list);
9714 free(in_ctxt);
9715 } else {
9716 ALOGW("%s, input stream already closed", __func__);
9717 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009718 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309719 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009720 return;
9721}
9722
Aalique Grahame22e49102018-12-18 14:23:57 -08009723/* verifies input and output devices and their capabilities.
9724 *
9725 * This verification is required when enabling extended bit-depth or
9726 * sampling rates, as not all qcom products support it.
9727 *
9728 * Suitable for calling only on initialization such as adev_open().
9729 * It fills the audio_device use_case_table[] array.
9730 *
9731 * Has a side-effect that it needs to configure audio routing / devices
9732 * in order to power up the devices and read the device parameters.
9733 * It does not acquire any hw device lock. Should restore the devices
9734 * back to "normal state" upon completion.
9735 */
9736static int adev_verify_devices(struct audio_device *adev)
9737{
9738 /* enumeration is a bit difficult because one really wants to pull
9739 * the use_case, device id, etc from the hidden pcm_device_table[].
9740 * In this case there are the following use cases and device ids.
9741 *
9742 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9743 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9744 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9745 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9746 * [USECASE_AUDIO_RECORD] = {0, 0},
9747 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9748 * [USECASE_VOICE_CALL] = {2, 2},
9749 *
9750 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9751 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9752 */
9753
9754 /* should be the usecases enabled in adev_open_input_stream() */
9755 static const int test_in_usecases[] = {
9756 USECASE_AUDIO_RECORD,
9757 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9758 };
9759 /* should be the usecases enabled in adev_open_output_stream()*/
9760 static const int test_out_usecases[] = {
9761 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9762 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9763 };
9764 static const usecase_type_t usecase_type_by_dir[] = {
9765 PCM_PLAYBACK,
9766 PCM_CAPTURE,
9767 };
9768 static const unsigned flags_by_dir[] = {
9769 PCM_OUT,
9770 PCM_IN,
9771 };
9772
9773 size_t i;
9774 unsigned dir;
9775 const unsigned card_id = adev->snd_card;
9776
9777 for (dir = 0; dir < 2; ++dir) {
9778 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9779 const unsigned flags_dir = flags_by_dir[dir];
9780 const size_t testsize =
9781 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9782 const int *testcases =
9783 dir ? test_in_usecases : test_out_usecases;
9784 const audio_devices_t audio_device =
9785 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9786
9787 for (i = 0; i < testsize; ++i) {
9788 const audio_usecase_t audio_usecase = testcases[i];
9789 int device_id;
9790 struct pcm_params **pparams;
9791 struct stream_out out;
9792 struct stream_in in;
9793 struct audio_usecase uc_info;
9794 int retval;
9795
9796 pparams = &adev->use_case_table[audio_usecase];
9797 pcm_params_free(*pparams); /* can accept null input */
9798 *pparams = NULL;
9799
9800 /* find the device ID for the use case (signed, for error) */
9801 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9802 if (device_id < 0)
9803 continue;
9804
9805 /* prepare structures for device probing */
9806 memset(&uc_info, 0, sizeof(uc_info));
9807 uc_info.id = audio_usecase;
9808 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009809 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009810 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009811 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009812 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009813 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009814 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9815 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009816 }
9817 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009818 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009819 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009820 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009821 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009822 uc_info.in_snd_device = SND_DEVICE_NONE;
9823 uc_info.out_snd_device = SND_DEVICE_NONE;
9824 list_add_tail(&adev->usecase_list, &uc_info.list);
9825
9826 /* select device - similar to start_(in/out)put_stream() */
9827 retval = select_devices(adev, audio_usecase);
9828 if (retval >= 0) {
9829 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9830#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009831 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009832 if (*pparams) {
9833 ALOGV("%s: (%s) card %d device %d", __func__,
9834 dir ? "input" : "output", card_id, device_id);
9835 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9836 } else {
9837 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9838 }
9839#endif
9840 }
9841
9842 /* deselect device - similar to stop_(in/out)put_stream() */
9843 /* 1. Get and set stream specific mixer controls */
9844 retval = disable_audio_route(adev, &uc_info);
9845 /* 2. Disable the rx device */
9846 retval = disable_snd_device(adev,
9847 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9848 list_remove(&uc_info.list);
9849 }
9850 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009851 return 0;
9852}
9853
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009854int update_patch(unsigned int num_sources,
9855 const struct audio_port_config *sources,
9856 unsigned int num_sinks,
9857 const struct audio_port_config *sinks,
9858 audio_patch_handle_t handle,
9859 struct audio_patch_info *p_info,
9860 patch_type_t patch_type, bool new_patch)
9861{
9862 ALOGD("%s: enter", __func__);
9863
9864 if (p_info == NULL) {
9865 ALOGE("%s: Invalid patch pointer", __func__);
9866 return -EINVAL;
9867 }
9868
9869 if (new_patch) {
9870 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9871 if (p_info->patch == NULL) {
9872 ALOGE("%s: Could not allocate patch", __func__);
9873 return -ENOMEM;
9874 }
9875 }
9876
9877 p_info->patch->id = handle;
9878 p_info->patch->num_sources = num_sources;
9879 p_info->patch->num_sinks = num_sinks;
9880
9881 for (int i = 0; i < num_sources; i++)
9882 p_info->patch->sources[i] = sources[i];
9883 for (int i = 0; i < num_sinks; i++)
9884 p_info->patch->sinks[i] = sinks[i];
9885
9886 p_info->patch_type = patch_type;
9887 return 0;
9888}
9889
9890audio_patch_handle_t generate_patch_handle()
9891{
9892 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9893 if (++patch_handle < 0)
9894 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9895 return patch_handle;
9896}
9897
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309898int adev_create_audio_patch(struct audio_hw_device *dev,
9899 unsigned int num_sources,
9900 const struct audio_port_config *sources,
9901 unsigned int num_sinks,
9902 const struct audio_port_config *sinks,
9903 audio_patch_handle_t *handle)
9904{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009905 int ret = 0;
9906 struct audio_device *adev = (struct audio_device *)dev;
9907 struct audio_patch_info *p_info = NULL;
9908 patch_type_t patch_type = PATCH_NONE;
9909 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9910 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9911 struct audio_stream_info *s_info = NULL;
9912 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009913 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009914 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9915 bool new_patch = false;
9916 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309917
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009918 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9919 num_sources, num_sinks, *handle);
9920
9921 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9922 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9923 ALOGE("%s: Invalid patch arguments", __func__);
9924 ret = -EINVAL;
9925 goto done;
9926 }
9927
9928 if (num_sources > 1) {
9929 ALOGE("%s: Multiple sources are not supported", __func__);
9930 ret = -EINVAL;
9931 goto done;
9932 }
9933
9934 if (sources == NULL || sinks == NULL) {
9935 ALOGE("%s: Invalid sources or sinks port config", __func__);
9936 ret = -EINVAL;
9937 goto done;
9938 }
9939
9940 ALOGV("%s: source role %d, source type %d", __func__,
9941 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009942 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009943
9944 // Populate source/sink information and fetch stream info
9945 switch (sources[0].type) {
9946 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9947 device_type = sources[0].ext.device.type;
9948 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009949 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009950 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9951 patch_type = PATCH_CAPTURE;
9952 io_handle = sinks[0].ext.mix.handle;
9953 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009954 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009955 __func__, device_type, io_handle);
9956 } else {
9957 // Device to device patch is not implemented.
9958 // This space will need changes if audio HAL
9959 // handles device to device patches in the future.
9960 patch_type = PATCH_DEVICE_LOOPBACK;
9961 }
9962 break;
9963 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9964 io_handle = sources[0].ext.mix.handle;
9965 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009966 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009967 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009968 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009969 }
9970 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009971 ALOGD("%s: Playback patch from mix handle %d to device %x",
9972 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009973 break;
9974 case AUDIO_PORT_TYPE_SESSION:
9975 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009976 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9977 ret = -EINVAL;
9978 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009979 }
9980
9981 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009982
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009983 // Generate patch info and update patch
9984 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009985 *handle = generate_patch_handle();
9986 p_info = (struct audio_patch_info *)
9987 calloc(1, sizeof(struct audio_patch_info));
9988 if (p_info == NULL) {
9989 ALOGE("%s: Failed to allocate memory", __func__);
9990 pthread_mutex_unlock(&adev->lock);
9991 ret = -ENOMEM;
9992 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009993 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009994 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009995 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009996 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009997 if (p_info == NULL) {
9998 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9999 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010000 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010001 ret = -EINVAL;
10002 goto done;
10003 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010004 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010005 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010006 *handle, p_info, patch_type, new_patch);
10007
10008 // Fetch stream info of associated mix for playback or capture patches
10009 if (p_info->patch_type == PATCH_PLAYBACK ||
10010 p_info->patch_type == PATCH_CAPTURE) {
10011 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10012 if (s_info == NULL) {
10013 ALOGE("%s: Failed to obtain stream info", __func__);
10014 if (new_patch)
10015 free(p_info);
10016 pthread_mutex_unlock(&adev->lock);
10017 ret = -EINVAL;
10018 goto done;
10019 }
10020 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
10021 s_info->patch_handle = *handle;
10022 stream = s_info->stream;
10023 }
10024 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010025
10026 // Update routing for stream
10027 if (stream != NULL) {
10028 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010029 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010030 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010031 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010032 if (ret < 0) {
10033 pthread_mutex_lock(&adev->lock);
10034 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10035 if (new_patch)
10036 free(p_info);
10037 pthread_mutex_unlock(&adev->lock);
10038 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10039 goto done;
10040 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010041 }
10042
10043 // Add new patch to patch map
10044 if (!ret && new_patch) {
10045 pthread_mutex_lock(&adev->lock);
10046 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010047 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010048 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010049 }
10050
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010051done:
10052 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010053 num_sources,
10054 sources,
10055 num_sinks,
10056 sinks,
10057 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010058 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -080010059 num_sources,
10060 sources,
10061 num_sinks,
10062 sinks,
10063 handle);
10064 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010065}
10066
10067int adev_release_audio_patch(struct audio_hw_device *dev,
10068 audio_patch_handle_t handle)
10069{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010070 struct audio_device *adev = (struct audio_device *) dev;
10071 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010072 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010073 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -080010074
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010075 if (handle == AUDIO_PATCH_HANDLE_NONE) {
10076 ALOGE("%s: Invalid patch handle %d", __func__, handle);
10077 ret = -EINVAL;
10078 goto done;
10079 }
10080
10081 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010082 pthread_mutex_lock(&adev->lock);
10083 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010084 if (p_info == NULL) {
10085 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010086 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010087 ret = -EINVAL;
10088 goto done;
10089 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010090 struct audio_patch *patch = p_info->patch;
10091 if (patch == NULL) {
10092 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010093 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010094 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010095 goto done;
10096 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010097 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10098 switch (patch->sources[0].type) {
10099 case AUDIO_PORT_TYPE_MIX:
10100 io_handle = patch->sources[0].ext.mix.handle;
10101 break;
10102 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010103 if (p_info->patch_type == PATCH_CAPTURE)
10104 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010105 break;
10106 case AUDIO_PORT_TYPE_SESSION:
10107 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010108 pthread_mutex_unlock(&adev->lock);
10109 ret = -EINVAL;
10110 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010111 }
10112
10113 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010114 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010115 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010116 if (patch_type == PATCH_PLAYBACK ||
10117 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010118 struct audio_stream_info *s_info =
10119 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10120 if (s_info == NULL) {
10121 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10122 pthread_mutex_unlock(&adev->lock);
10123 goto done;
10124 }
10125 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10126 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010127 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010128 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010129
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010130 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010131 struct listnode devices;
10132 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010133 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010134 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010135 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010136 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010137 }
10138
10139 if (ret < 0)
10140 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10141
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010142done:
10143 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10144 audio_extn_auto_hal_release_audio_patch(dev, handle);
10145
10146 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010147 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010148}
10149
10150int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10151{
Derek Chenf13dd492018-11-13 14:53:51 -080010152 int ret = 0;
10153
10154 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10155 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10156 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010157}
10158
10159int adev_set_audio_port_config(struct audio_hw_device *dev,
10160 const struct audio_port_config *config)
10161{
Derek Chenf13dd492018-11-13 14:53:51 -080010162 int ret = 0;
10163
10164 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10165 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10166 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010167}
10168
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010169static int adev_dump(const audio_hw_device_t *device __unused,
10170 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010171{
10172 return 0;
10173}
10174
10175static int adev_close(hw_device_t *device)
10176{
Aalique Grahame22e49102018-12-18 14:23:57 -080010177 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010178 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010179
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010180 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010181 return 0;
10182
10183 pthread_mutex_lock(&adev_init_lock);
10184
10185 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010186 if (audio_extn_spkr_prot_is_enabled())
10187 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010188 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010189 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010190 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010191 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010192 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010193 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010194 audio_extn_utils_release_streams_cfg_lists(
10195 &adev->streams_output_cfg_list,
10196 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010197 if (audio_extn_qap_is_enabled())
10198 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010199 if (audio_extn_qaf_is_enabled())
10200 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010201 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010202 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010203 free(adev->snd_dev_ref_cnt);
10204 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010205 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10206 pcm_params_free(adev->use_case_table[i]);
10207 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010208 if (adev->adm_deinit)
10209 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010210 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010211 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010212 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010213 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010214 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010215 if (adev->device_cfg_params) {
10216 free(adev->device_cfg_params);
10217 adev->device_cfg_params = NULL;
10218 }
Derek Chend2530072014-11-24 12:39:14 -080010219 if(adev->ext_hw_plugin)
10220 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010221 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010222 free_map(adev->patch_map);
10223 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010224 free(device);
10225 adev = NULL;
10226 }
10227 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010228 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010229 return 0;
10230}
10231
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010232/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10233 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10234 * just that it _might_ work.
10235 */
10236static int period_size_is_plausible_for_low_latency(int period_size)
10237{
10238 switch (period_size) {
10239 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010240 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010241 case 240:
10242 case 320:
10243 case 480:
10244 return 1;
10245 default:
10246 return 0;
10247 }
10248}
10249
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010250static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10251{
10252 bool is_snd_card_status = false;
10253 bool is_ext_device_status = false;
10254 char value[32];
10255 int card = -1;
10256 card_status_t status;
10257
10258 if (cookie != adev || !parms)
10259 return;
10260
10261 if (!parse_snd_card_status(parms, &card, &status)) {
10262 is_snd_card_status = true;
10263 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10264 is_ext_device_status = true;
10265 } else {
10266 // not a valid event
10267 return;
10268 }
10269
10270 pthread_mutex_lock(&adev->lock);
10271 if (card == adev->snd_card || is_ext_device_status) {
10272 if (is_snd_card_status && adev->card_status != status) {
10273 adev->card_status = status;
10274 platform_snd_card_update(adev->platform, status);
10275 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010276 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010277 if (status == CARD_STATUS_OFFLINE)
10278 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010279 } else if (is_ext_device_status) {
10280 platform_set_parameters(adev->platform, parms);
10281 }
10282 }
10283 pthread_mutex_unlock(&adev->lock);
10284 return;
10285}
10286
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010287/* out and adev lock held */
10288static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10289{
10290 struct audio_usecase *uc_info;
10291 float left_p;
10292 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010293 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010294
10295 uc_info = get_usecase_from_list(adev, out->usecase);
10296 if (uc_info == NULL) {
10297 ALOGE("%s: Could not find the usecase (%d) in the list",
10298 __func__, out->usecase);
10299 return -EINVAL;
10300 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010301 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010302
10303 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10304 out->usecase, use_case_table[out->usecase]);
10305
10306 if (restore) {
10307 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010308 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010309 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010310 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10311 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010312 pthread_mutex_lock(&out->compr_mute_lock);
10313 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010314 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010315 out->a2dp_compress_mute = false;
10316 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10317 }
10318 pthread_mutex_unlock(&out->compr_mute_lock);
10319 }
10320 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010321 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10322 // mute compress stream if suspended
10323 pthread_mutex_lock(&out->compr_mute_lock);
10324 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010325 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010326 assign_devices(&devices, &out->device_list);
10327 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010328 left_p = out->volume_l;
10329 right_p = out->volume_r;
10330 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10331 compress_pause(out->compr);
10332 out_set_compr_volume(&out->stream, (float)0, (float)0);
10333 out->a2dp_compress_mute = true;
10334 select_devices(adev, out->usecase);
10335 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10336 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010337 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010338 out->volume_l = left_p;
10339 out->volume_r = right_p;
10340 }
Zhou Songc576a452019-09-09 14:17:40 +080010341 pthread_mutex_unlock(&out->compr_mute_lock);
10342 } else {
10343 // tear down a2dp path for non offloaded streams
10344 if (audio_extn_a2dp_source_is_suspended())
10345 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010346 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010347 }
10348 ALOGV("%s: exit", __func__);
10349 return 0;
10350}
10351
10352int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10353{
10354 int ret = 0;
10355
10356 lock_output_stream(out);
10357 pthread_mutex_lock(&adev->lock);
10358
10359 ret = check_a2dp_restore_l(adev, out, restore);
10360
10361 pthread_mutex_unlock(&adev->lock);
10362 pthread_mutex_unlock(&out->lock);
10363 return ret;
10364}
10365
Haynes Mathew George01156f92018-04-13 15:29:54 -070010366void adev_on_battery_status_changed(bool charging)
10367{
10368 pthread_mutex_lock(&adev->lock);
10369 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10370 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010371 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010372 pthread_mutex_unlock(&adev->lock);
10373}
10374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010375static int adev_open(const hw_module_t *module, const char *name,
10376 hw_device_t **device)
10377{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010378 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010379 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010380 char mixer_ctl_name[128] = {0};
10381 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010382
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010383 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010384 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10385
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010386 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010387 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010388 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010389 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010390 ALOGD("%s: returning existing instance of adev", __func__);
10391 ALOGD("%s: exit", __func__);
10392 pthread_mutex_unlock(&adev_init_lock);
10393 return 0;
10394 }
10395
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010396 adev = calloc(1, sizeof(struct audio_device));
10397
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010398 if (!adev) {
10399 pthread_mutex_unlock(&adev_init_lock);
10400 return -ENOMEM;
10401 }
10402
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010403 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10404
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010405 // register audio ext hidl at the earliest
10406 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010407#ifdef DYNAMIC_LOG_ENABLED
10408 register_for_dynamic_logging("hal");
10409#endif
10410
Derek Chenf939fb72018-11-13 13:34:41 -080010411 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010412 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010413 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10414 maj_version = atoi(value);
10415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010416 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010417 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010418 adev->device.common.module = (struct hw_module_t *)module;
10419 adev->device.common.close = adev_close;
10420
10421 adev->device.init_check = adev_init_check;
10422 adev->device.set_voice_volume = adev_set_voice_volume;
10423 adev->device.set_master_volume = adev_set_master_volume;
10424 adev->device.get_master_volume = adev_get_master_volume;
10425 adev->device.set_master_mute = adev_set_master_mute;
10426 adev->device.get_master_mute = adev_get_master_mute;
10427 adev->device.set_mode = adev_set_mode;
10428 adev->device.set_mic_mute = adev_set_mic_mute;
10429 adev->device.get_mic_mute = adev_get_mic_mute;
10430 adev->device.set_parameters = adev_set_parameters;
10431 adev->device.get_parameters = adev_get_parameters;
10432 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10433 adev->device.open_output_stream = adev_open_output_stream;
10434 adev->device.close_output_stream = adev_close_output_stream;
10435 adev->device.open_input_stream = adev_open_input_stream;
10436 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010437 adev->device.create_audio_patch = adev_create_audio_patch;
10438 adev->device.release_audio_patch = adev_release_audio_patch;
10439 adev->device.get_audio_port = adev_get_audio_port;
10440 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010441 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010442 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010443
10444 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010445 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010446 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010447 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010448 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010449 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010450 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010451 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010452 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010453 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010454 /* Init audio and voice feature */
10455 audio_extn_feature_init();
10456 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010457 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010458 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010459 list_init(&adev->active_inputs_list);
10460 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010461 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010462 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10463 audio_extn_utils_hash_eq);
10464 if (!adev->io_streams_map) {
10465 ALOGE("%s: Could not create io streams map", __func__);
10466 ret = -ENOMEM;
10467 goto adev_open_err;
10468 }
10469 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10470 audio_extn_utils_hash_eq);
10471 if (!adev->patch_map) {
10472 ALOGE("%s: Could not create audio patch map", __func__);
10473 ret = -ENOMEM;
10474 goto adev_open_err;
10475 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010476 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010477 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010478 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010479 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010480 adev->perf_lock_opts[0] = 0x101;
10481 adev->perf_lock_opts[1] = 0x20E;
10482 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010483 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010484 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010485 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010486 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010487
Zhou Song68ebc352019-12-05 17:11:15 +080010488 audio_extn_perf_lock_init();
10489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010490 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010491 adev->platform = platform_init(adev);
10492 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010493 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010494 ret = -EINVAL;
10495 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010496 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010497
Aalique Grahame22e49102018-12-18 14:23:57 -080010498 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010499 if (audio_extn_qap_is_enabled()) {
10500 ret = audio_extn_qap_init(adev);
10501 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010502 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010503 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010504 }
10505 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10506 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10507 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010508
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010509 if (audio_extn_qaf_is_enabled()) {
10510 ret = audio_extn_qaf_init(adev);
10511 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010512 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010513 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010514 }
10515
10516 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10517 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10518 }
10519
Derek Chenae7b0342019-02-08 15:17:04 -080010520 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010521 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10522
Eric Laurentc4aef752013-09-12 17:45:53 -070010523 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10524 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10525 if (adev->visualizer_lib == NULL) {
10526 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10527 } else {
10528 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10529 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010530 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010531 "visualizer_hal_start_output");
10532 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010533 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010534 "visualizer_hal_stop_output");
10535 }
10536 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010537 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010538 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010539 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010540 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010541 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010542 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010543
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010544 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10545 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10546 if (adev->offload_effects_lib == NULL) {
10547 ALOGE("%s: DLOPEN failed for %s", __func__,
10548 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10549 } else {
10550 ALOGV("%s: DLOPEN successful for %s", __func__,
10551 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10552 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010553 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010554 "offload_effects_bundle_hal_start_output");
10555 adev->offload_effects_stop_output =
10556 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10557 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010558 adev->offload_effects_set_hpx_state =
10559 (int (*)(bool))dlsym(adev->offload_effects_lib,
10560 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010561 adev->offload_effects_get_parameters =
10562 (void (*)(struct str_parms *, struct str_parms *))
10563 dlsym(adev->offload_effects_lib,
10564 "offload_effects_bundle_get_parameters");
10565 adev->offload_effects_set_parameters =
10566 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10567 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010568 }
10569 }
10570
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010571 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10572 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10573 if (adev->adm_lib == NULL) {
10574 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10575 } else {
10576 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10577 adev->adm_init = (adm_init_t)
10578 dlsym(adev->adm_lib, "adm_init");
10579 adev->adm_deinit = (adm_deinit_t)
10580 dlsym(adev->adm_lib, "adm_deinit");
10581 adev->adm_register_input_stream = (adm_register_input_stream_t)
10582 dlsym(adev->adm_lib, "adm_register_input_stream");
10583 adev->adm_register_output_stream = (adm_register_output_stream_t)
10584 dlsym(adev->adm_lib, "adm_register_output_stream");
10585 adev->adm_deregister_stream = (adm_deregister_stream_t)
10586 dlsym(adev->adm_lib, "adm_deregister_stream");
10587 adev->adm_request_focus = (adm_request_focus_t)
10588 dlsym(adev->adm_lib, "adm_request_focus");
10589 adev->adm_abandon_focus = (adm_abandon_focus_t)
10590 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010591 adev->adm_set_config = (adm_set_config_t)
10592 dlsym(adev->adm_lib, "adm_set_config");
10593 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10594 dlsym(adev->adm_lib, "adm_request_focus_v2");
10595 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10596 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10597 adev->adm_on_routing_change = (adm_on_routing_change_t)
10598 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010599 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10600 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010601 }
10602 }
10603
Aalique Grahame22e49102018-12-18 14:23:57 -080010604 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010605 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010606 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010607 //initialize this to false for now,
10608 //this will be set to true through set param
10609 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010610
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010611 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010612 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010613
10614 if (k_enable_extended_precision)
10615 adev_verify_devices(adev);
10616
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010617 adev->dsp_bit_width_enforce_mode =
10618 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010619
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010620 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10621 &adev->streams_output_cfg_list,
10622 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010623
Kiran Kandi910e1862013-10-29 13:29:42 -070010624 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010625
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010626 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010627 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010628 trial = atoi(value);
10629 if (period_size_is_plausible_for_low_latency(trial)) {
10630 pcm_config_low_latency.period_size = trial;
10631 pcm_config_low_latency.start_threshold = trial / 4;
10632 pcm_config_low_latency.avail_min = trial / 4;
10633 configured_low_latency_capture_period_size = trial;
10634 }
10635 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010636 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10637 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010638 trial = atoi(value);
10639 if (period_size_is_plausible_for_low_latency(trial)) {
10640 configured_low_latency_capture_period_size = trial;
10641 }
10642 }
10643
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010644 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10645
Eric Laurent4b084132018-10-19 17:33:43 -070010646 adev->camera_orientation = CAMERA_DEFAULT;
10647
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010648 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010649 af_period_multiplier = atoi(value);
10650 if (af_period_multiplier < 0)
10651 af_period_multiplier = 2;
10652 else if (af_period_multiplier > 4)
10653 af_period_multiplier = 4;
10654
10655 ALOGV("new period_multiplier = %d", af_period_multiplier);
10656 }
10657
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010658 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010659
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010660 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010661 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010662 pthread_mutex_unlock(&adev_init_lock);
10663
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010664 if (adev->adm_init)
10665 adev->adm_data = adev->adm_init();
10666
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010667 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010668 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010669
10670 audio_extn_snd_mon_init();
10671 pthread_mutex_lock(&adev->lock);
10672 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10673 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010674 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10675 /*
10676 * if the battery state callback happens before charging can be queried,
10677 * it will be guarded with the adev->lock held in the cb function and so
10678 * the callback value will reflect the latest state
10679 */
10680 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010681 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010682 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010683 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010684 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010685 /* Allocate memory for Device config params */
10686 adev->device_cfg_params = (struct audio_device_config_param*)
10687 calloc(platform_get_max_codec_backend(),
10688 sizeof(struct audio_device_config_param));
10689 if (adev->device_cfg_params == NULL)
10690 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010691
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010692 /*
10693 * Check if new PSPD matrix mixer control is supported. If not
10694 * supported, then set flag so that old mixer ctrl is sent while
10695 * sending pspd coefficients on older kernel version. Query mixer
10696 * control for default pcm id and channel value one.
10697 */
10698 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10699 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10700
10701 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10702 if (!ctl) {
10703 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10704 __func__, mixer_ctl_name);
10705 adev->use_old_pspd_mix_ctrl = true;
10706 }
10707
Eric Laurent994a6932013-07-17 11:51:42 -070010708 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010709 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010710
10711adev_open_err:
10712 free_map(adev->patch_map);
10713 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010714 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010715 pthread_mutex_destroy(&adev->lock);
10716 free(adev);
10717 adev = NULL;
10718 *device = NULL;
10719 pthread_mutex_unlock(&adev_init_lock);
10720 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010721}
10722
10723static struct hw_module_methods_t hal_module_methods = {
10724 .open = adev_open,
10725};
10726
10727struct audio_module HAL_MODULE_INFO_SYM = {
10728 .common = {
10729 .tag = HARDWARE_MODULE_TAG,
10730 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10731 .hal_api_version = HARDWARE_HAL_API_VERSION,
10732 .id = AUDIO_HARDWARE_MODULE_ID,
10733 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010734 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010735 .methods = &hal_module_methods,
10736 },
10737};