blob: 17dd29041402a7dbf4ce2bd7146c889ac2e9ee8a [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Andy Hunga1f48fa2019-07-01 18:14:53 -070068#include <utils/Timers.h> // systemTime
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include <audio_effects/effect_aec.h>
70#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053071#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080073#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070074#include "platform_api.h"
75#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070076#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080077#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053078#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080081#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080082
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053083#ifdef DYNAMIC_LOG_ENABLED
84#include <log_xml_parser.h>
85#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
86#include <log_utils.h>
87#endif
88
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053090/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
91#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070093#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070094#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053095#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053096#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070097#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070098#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070099
Aalique Grahame22e49102018-12-18 14:23:57 -0800100#define RECORD_GAIN_MIN 0.0f
101#define RECORD_GAIN_MAX 1.0f
102#define RECORD_VOLUME_CTL_MAX 0x2000
103
104/* treat as unsigned Q1.13 */
105#define APP_TYPE_GAIN_DEFAULT 0x2000
106
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700107#define PROXY_OPEN_RETRY_COUNT 100
108#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800109
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800110#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
111 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
112 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
113#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
114 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800115
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700116#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700117#define DEFAULT_VOIP_BUF_DURATION_MS 20
118#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
119#define DEFAULT_VOIP_SAMP_RATE 48000
120
121#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
122
123struct pcm_config default_pcm_config_voip_copp = {
124 .channels = 1,
125 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
126 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
127 .period_count = 2,
128 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800129 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
130 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700131};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700132
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700133#define MIN_CHANNEL_COUNT 1
134#define DEFAULT_CHANNEL_COUNT 2
135#define MAX_HIFI_CHANNEL_COUNT 8
136
Aalique Grahame22e49102018-12-18 14:23:57 -0800137#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
138#define MAX_CHANNEL_COUNT 1
139#else
140#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
141#define XSTR(x) STR(x)
142#define STR(x) #x
143#endif
144
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700145static unsigned int configured_low_latency_capture_period_size =
146 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
147
Haynes Mathew George16081042017-05-31 17:16:49 -0700148#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
149#define MMAP_PERIOD_COUNT_MIN 32
150#define MMAP_PERIOD_COUNT_MAX 512
151#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
152
Aalique Grahame22e49102018-12-18 14:23:57 -0800153/* This constant enables extended precision handling.
154 * TODO The flag is off until more testing is done.
155 */
156static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700157extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800158
Eric Laurentb23d5282013-05-14 15:27:20 -0700159struct pcm_config pcm_config_deep_buffer = {
160 .channels = 2,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
163 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
166 .stop_threshold = INT_MAX,
167 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
168};
169
170struct pcm_config pcm_config_low_latency = {
171 .channels = 2,
172 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
173 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
174 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
175 .format = PCM_FORMAT_S16_LE,
176 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
177 .stop_threshold = INT_MAX,
178 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
179};
180
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800181struct pcm_config pcm_config_haptics_audio = {
182 .channels = 1,
183 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
184 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
185 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
187 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
188 .stop_threshold = INT_MAX,
189 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
190};
191
192struct pcm_config pcm_config_haptics = {
193 .channels = 1,
194 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
195 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
196 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
197 .format = PCM_FORMAT_S16_LE,
198 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
199 .stop_threshold = INT_MAX,
200 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
201};
202
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700203static int af_period_multiplier = 4;
204struct pcm_config pcm_config_rt = {
205 .channels = 2,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = ULL_PERIOD_SIZE, //1 ms
208 .period_count = 512, //=> buffer size is 512ms
209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = ULL_PERIOD_SIZE, //1 ms
215};
216
Eric Laurentb23d5282013-05-14 15:27:20 -0700217struct pcm_config pcm_config_hdmi_multi = {
218 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
219 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
220 .period_size = HDMI_MULTI_PERIOD_SIZE,
221 .period_count = HDMI_MULTI_PERIOD_COUNT,
222 .format = PCM_FORMAT_S16_LE,
223 .start_threshold = 0,
224 .stop_threshold = INT_MAX,
225 .avail_min = 0,
226};
227
Haynes Mathew George16081042017-05-31 17:16:49 -0700228struct pcm_config pcm_config_mmap_playback = {
229 .channels = 2,
230 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
231 .period_size = MMAP_PERIOD_SIZE,
232 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
233 .format = PCM_FORMAT_S16_LE,
234 .start_threshold = MMAP_PERIOD_SIZE*8,
235 .stop_threshold = INT32_MAX,
236 .silence_threshold = 0,
237 .silence_size = 0,
238 .avail_min = MMAP_PERIOD_SIZE, //1 ms
239};
240
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700241struct pcm_config pcm_config_hifi = {
242 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
243 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
244 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
245 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
246 .format = PCM_FORMAT_S24_3LE,
247 .start_threshold = 0,
248 .stop_threshold = INT_MAX,
249 .avail_min = 0,
250};
251
Eric Laurentb23d5282013-05-14 15:27:20 -0700252struct pcm_config pcm_config_audio_capture = {
253 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700254 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
255 .format = PCM_FORMAT_S16_LE,
256};
257
Haynes Mathew George16081042017-05-31 17:16:49 -0700258struct pcm_config pcm_config_mmap_capture = {
259 .channels = 2,
260 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
261 .period_size = MMAP_PERIOD_SIZE,
262 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
263 .format = PCM_FORMAT_S16_LE,
264 .start_threshold = 0,
265 .stop_threshold = INT_MAX,
266 .silence_threshold = 0,
267 .silence_size = 0,
268 .avail_min = MMAP_PERIOD_SIZE, //1 ms
269};
270
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700271#define AFE_PROXY_CHANNEL_COUNT 2
272#define AFE_PROXY_SAMPLING_RATE 48000
273
274#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
275#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
276
277struct pcm_config pcm_config_afe_proxy_playback = {
278 .channels = AFE_PROXY_CHANNEL_COUNT,
279 .rate = AFE_PROXY_SAMPLING_RATE,
280 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
281 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
282 .format = PCM_FORMAT_S16_LE,
283 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
284 .stop_threshold = INT_MAX,
285 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
286};
287
288#define AFE_PROXY_RECORD_PERIOD_SIZE 768
289#define AFE_PROXY_RECORD_PERIOD_COUNT 4
290
Aalique Grahame22e49102018-12-18 14:23:57 -0800291struct pcm_config pcm_config_audio_capture_rt = {
292 .channels = 2,
293 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
294 .period_size = ULL_PERIOD_SIZE,
295 .period_count = 512,
296 .format = PCM_FORMAT_S16_LE,
297 .start_threshold = 0,
298 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
299 .silence_threshold = 0,
300 .silence_size = 0,
301 .avail_min = ULL_PERIOD_SIZE, //1 ms
302};
303
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700304struct pcm_config pcm_config_afe_proxy_record = {
305 .channels = AFE_PROXY_CHANNEL_COUNT,
306 .rate = AFE_PROXY_SAMPLING_RATE,
307 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
308 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
309 .format = PCM_FORMAT_S16_LE,
310 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
311 .stop_threshold = INT_MAX,
312 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
313};
314
Ashish Jainf1eaa582016-05-23 20:54:24 +0530315#define AUDIO_MAX_PCM_FORMATS 7
316
317const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
318 [AUDIO_FORMAT_DEFAULT] = 0,
319 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
320 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
321 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
322 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
323 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
324 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
325};
326
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800327const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700328 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
329 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800330 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700331 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
332 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700333 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700334 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700335 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
341 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
342 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700343 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
344 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700345 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800346 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700347
Eric Laurentb23d5282013-05-14 15:27:20 -0700348 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700349 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530350 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
351 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
352 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530353 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
354 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700355 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700356 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700357 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700358 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700359
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800360 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800361 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400362 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
363 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700364
Derek Chenf7092792017-05-23 12:23:53 -0400365 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700366 [USECASE_VOICE2_CALL] = "voice2-call",
367 [USECASE_VOLTE_CALL] = "volte-call",
368 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800369 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800370 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
371 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800372 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700373 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
374 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
375 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800376 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
377 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
378 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
379
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700380 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
381 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700382 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
383 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700384
385 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
386 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530387 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700388
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530389 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530390 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
391 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700392
393 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
394 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530395 /* For Interactive Audio Streams */
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
401 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
402 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
403 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700404
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800405 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
406
Derek Chenf6318be2017-06-12 17:16:24 -0400407 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
408
409 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
410 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
411 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
412 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700413 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530414 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700415};
416
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700417static const audio_usecase_t offload_usecases[] = {
418 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700419 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
420 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
421 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
422 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
426 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700427};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800428
Varun Balaraje49253e2017-07-06 19:48:56 +0530429static const audio_usecase_t interactive_usecases[] = {
430 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
432 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
437 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
438};
439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800440#define STRING_TO_ENUM(string) { #string, string }
441
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800442struct string_to_enum {
443 const char *name;
444 uint32_t value;
445};
446
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700447static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800448 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
450 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800455 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700456 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
457 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
458 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
459 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
461 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
466 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800467};
468
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700469static const struct string_to_enum formats_name_to_enum_table[] = {
470 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
471 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
472 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700473 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
474 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
475 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700476 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800477 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
478 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700479 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800480};
481
482//list of all supported sample rates by HDMI specification.
483static const int out_hdmi_sample_rates[] = {
484 32000, 44100, 48000, 88200, 96000, 176400, 192000,
485};
486
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700487static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800488 STRING_TO_ENUM(32000),
489 STRING_TO_ENUM(44100),
490 STRING_TO_ENUM(48000),
491 STRING_TO_ENUM(88200),
492 STRING_TO_ENUM(96000),
493 STRING_TO_ENUM(176400),
494 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800495 STRING_TO_ENUM(352800),
496 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700497};
498
Carter Hsu2e429db2019-05-14 18:50:52 +0800499struct in_effect_list {
500 struct listnode list;
501 effect_handle_t handle;
502};
503
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700504static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700505static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700506static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700507//cache last MBDRC cal step level
508static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700509
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530510static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
511static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700512static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800513static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530514static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530515
Derek Chen6f293672019-04-01 01:40:24 -0700516static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
517static void in_snd_mon_cb(void * stream, struct str_parms * parms);
518static void out_snd_mon_cb(void * stream, struct str_parms * parms);
519
Zhou Song331c8e52019-08-26 14:16:12 +0800520static int configure_btsco_sample_rate(snd_device_t snd_device);
521
Vatsal Buchac09ae062018-11-14 13:25:08 +0530522#ifdef AUDIO_FEATURE_ENABLED_GCOV
523extern void __gcov_flush();
524static void enable_gcov()
525{
526 __gcov_flush();
527}
528#else
529static void enable_gcov()
530{
531}
532#endif
533
justinweng20fb6d82019-02-21 18:49:00 -0700534static int in_set_microphone_direction(const struct audio_stream_in *stream,
535 audio_microphone_direction_t dir);
536static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
537
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700538static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
539 int flags __unused)
540{
541 int dir = 0;
542 switch (uc_id) {
543 case USECASE_AUDIO_RECORD_LOW_LATENCY:
544 dir = 1;
545 case USECASE_AUDIO_PLAYBACK_ULL:
546 break;
547 default:
548 return false;
549 }
550
551 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
552 PCM_PLAYBACK : PCM_CAPTURE);
553 if (adev->adm_is_noirq_avail)
554 return adev->adm_is_noirq_avail(adev->adm_data,
555 adev->snd_card, dev_id, dir);
556 return false;
557}
558
559static void register_out_stream(struct stream_out *out)
560{
561 struct audio_device *adev = out->dev;
562 if (is_offload_usecase(out->usecase) ||
563 !adev->adm_register_output_stream)
564 return;
565
566 // register stream first for backward compatibility
567 adev->adm_register_output_stream(adev->adm_data,
568 out->handle,
569 out->flags);
570
571 if (!adev->adm_set_config)
572 return;
573
574 if (out->realtime)
575 adev->adm_set_config(adev->adm_data,
576 out->handle,
577 out->pcm, &out->config);
578}
579
580static void register_in_stream(struct stream_in *in)
581{
582 struct audio_device *adev = in->dev;
583 if (!adev->adm_register_input_stream)
584 return;
585
586 adev->adm_register_input_stream(adev->adm_data,
587 in->capture_handle,
588 in->flags);
589
590 if (!adev->adm_set_config)
591 return;
592
593 if (in->realtime)
594 adev->adm_set_config(adev->adm_data,
595 in->capture_handle,
596 in->pcm,
597 &in->config);
598}
599
600static void request_out_focus(struct stream_out *out, long ns)
601{
602 struct audio_device *adev = out->dev;
603
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700604 if (adev->adm_request_focus_v2)
605 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
606 else if (adev->adm_request_focus)
607 adev->adm_request_focus(adev->adm_data, out->handle);
608}
609
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700610static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700611{
612 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700613 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700614
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700615 if (adev->adm_request_focus_v2_1)
616 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
617 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700618 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
619 else if (adev->adm_request_focus)
620 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700621
622 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700623}
624
625static void release_out_focus(struct stream_out *out)
626{
627 struct audio_device *adev = out->dev;
628
629 if (adev->adm_abandon_focus)
630 adev->adm_abandon_focus(adev->adm_data, out->handle);
631}
632
633static void release_in_focus(struct stream_in *in)
634{
635 struct audio_device *adev = in->dev;
636 if (adev->adm_abandon_focus)
637 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
638}
639
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530640static int parse_snd_card_status(struct str_parms *parms, int *card,
641 card_status_t *status)
642{
643 char value[32]={0};
644 char state[32]={0};
645
646 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
647 if (ret < 0)
648 return -1;
649
650 // sscanf should be okay as value is of max length 32.
651 // same as sizeof state.
652 if (sscanf(value, "%d,%s", card, state) < 2)
653 return -1;
654
655 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
656 CARD_STATUS_OFFLINE;
657 return 0;
658}
659
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700660static inline void adjust_frames_for_device_delay(struct stream_out *out,
661 uint32_t *dsp_frames) {
662 // Adjustment accounts for A2dp encoder latency with offload usecases
663 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800664 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700665 unsigned long offset =
666 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
667 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
668 }
669}
670
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700671static inline bool free_entry(void *key __unused,
672 void *value, void *context __unused)
673{
674 free(value);
675 return true;
676}
677
678static inline void free_map(Hashmap *map)
679{
680 if (map) {
681 hashmapForEach(map, free_entry, (void *) NULL);
682 hashmapFree(map);
683 }
684}
685
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800686static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700687 audio_patch_handle_t patch_handle)
688{
689 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
690 return;
691
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700692 struct audio_patch_info *p_info =
693 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
694 if (p_info) {
695 ALOGV("%s: Remove patch %d", __func__, patch_handle);
696 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
697 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700698 free(p_info);
699 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700700}
701
702static inline int io_streams_map_insert(struct audio_device *adev,
703 struct audio_stream *stream,
704 audio_io_handle_t handle,
705 audio_patch_handle_t patch_handle)
706{
707 struct audio_stream_info *s_info =
708 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
709
710 if (s_info == NULL) {
711 ALOGE("%s: Could not allocate stream info", __func__);
712 return -ENOMEM;
713 }
714 s_info->stream = stream;
715 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700716
717 pthread_mutex_lock(&adev->lock);
718 struct audio_stream_info *stream_info =
719 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700720 if (stream_info != NULL)
721 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800722 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700723 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
724 return 0;
725}
726
727static inline void io_streams_map_remove(struct audio_device *adev,
728 audio_io_handle_t handle)
729{
730 pthread_mutex_lock(&adev->lock);
731 struct audio_stream_info *s_info =
732 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700733 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800734 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700735 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800736 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700737 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800738done:
739 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700740 return;
741}
742
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800743static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700744 audio_patch_handle_t handle)
745{
746 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 p_info = (struct audio_patch_info *)
748 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700749 return p_info;
750}
751
vivek mehtaa76401a2015-04-24 14:12:15 -0700752__attribute__ ((visibility ("default")))
753bool audio_hw_send_gain_dep_calibration(int level) {
754 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700755 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700756
757 pthread_mutex_lock(&adev_init_lock);
758
759 if (adev != NULL && adev->platform != NULL) {
760 pthread_mutex_lock(&adev->lock);
761 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700762
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530763 // cache level info for any of the use case which
764 // was not started.
765 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700766
vivek mehtaa76401a2015-04-24 14:12:15 -0700767 pthread_mutex_unlock(&adev->lock);
768 } else {
769 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
770 }
771
772 pthread_mutex_unlock(&adev_init_lock);
773
774 return ret_val;
775}
776
Ashish Jain5106d362016-05-11 19:23:33 +0530777static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
778{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800779 bool gapless_enabled = false;
780 const char *mixer_ctl_name = "Compress Gapless Playback";
781 struct mixer_ctl *ctl;
782
783 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700784 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530785
786 /*Disable gapless if its AV playback*/
787 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800788
789 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
790 if (!ctl) {
791 ALOGE("%s: Could not get ctl for mixer cmd - %s",
792 __func__, mixer_ctl_name);
793 return -EINVAL;
794 }
795
796 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
797 ALOGE("%s: Could not set gapless mode %d",
798 __func__, gapless_enabled);
799 return -EINVAL;
800 }
801 return 0;
802}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700803
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700804__attribute__ ((visibility ("default")))
805int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
806 int table_size) {
807 int ret_val = 0;
808 ALOGV("%s: enter ... ", __func__);
809
810 pthread_mutex_lock(&adev_init_lock);
811 if (adev == NULL) {
812 ALOGW("%s: adev is NULL .... ", __func__);
813 goto done;
814 }
815
816 pthread_mutex_lock(&adev->lock);
817 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
818 pthread_mutex_unlock(&adev->lock);
819done:
820 pthread_mutex_unlock(&adev_init_lock);
821 ALOGV("%s: exit ... ", __func__);
822 return ret_val;
823}
824
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800825bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800826{
827 bool ret = false;
828 ALOGV("%s: enter ...", __func__);
829
830 pthread_mutex_lock(&adev_init_lock);
831
832 if (adev != NULL && adev->platform != NULL) {
833 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800834 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800835 pthread_mutex_unlock(&adev->lock);
836 }
837
838 pthread_mutex_unlock(&adev_init_lock);
839
840 ALOGV("%s: exit with ret %d", __func__, ret);
841 return ret;
842}
Aalique Grahame22e49102018-12-18 14:23:57 -0800843
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700844static bool is_supported_format(audio_format_t format)
845{
Eric Laurent86e17132013-09-12 17:49:30 -0700846 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530847 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530848 format == AUDIO_FORMAT_AAC_LC ||
849 format == AUDIO_FORMAT_AAC_HE_V1 ||
850 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530851 format == AUDIO_FORMAT_AAC_ADTS_LC ||
852 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
853 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530854 format == AUDIO_FORMAT_AAC_LATM_LC ||
855 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
856 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530857 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
858 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530859 format == AUDIO_FORMAT_PCM_FLOAT ||
860 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700861 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530862 format == AUDIO_FORMAT_AC3 ||
863 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700864 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530865 format == AUDIO_FORMAT_DTS ||
866 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800867 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530868 format == AUDIO_FORMAT_ALAC ||
869 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530870 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530871 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800872 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530873 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700874 format == AUDIO_FORMAT_APTX ||
875 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800876 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700877
878 return false;
879}
880
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700881static inline bool is_mmap_usecase(audio_usecase_t uc_id)
882{
883 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
884 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
885}
886
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700887static inline bool is_valid_volume(float left, float right)
888{
889 return ((left >= 0.0f && right >= 0.0f) ? true : false);
890}
891
Avinash Vaish71a8b972014-07-24 15:36:33 +0530892static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
893 struct audio_usecase *uc_info)
894{
895 struct listnode *node;
896 struct audio_usecase *usecase;
897
898 if (uc_info == NULL)
899 return -EINVAL;
900
901 /* Re-route all voice usecases on the shared backend other than the
902 specified usecase to new snd devices */
903 list_for_each(node, &adev->usecase_list) {
904 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800905 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530906 enable_audio_route(adev, usecase);
907 }
908 return 0;
909}
910
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530911static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530912{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530913 ALOGV("%s", __func__);
914 audio_route_apply_and_update_path(adev->audio_route,
915 "asrc-mode");
916 adev->asrc_mode_enabled = true;
917}
918
919static void disable_asrc_mode(struct audio_device *adev)
920{
921 ALOGV("%s", __func__);
922 audio_route_reset_and_update_path(adev->audio_route,
923 "asrc-mode");
924 adev->asrc_mode_enabled = false;
925}
926
927/*
928 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
929 * 44.1 or Native DSD backends are enabled for any of current use case.
930 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
931 * - Disable current mix path use case(Headphone backend) and re-enable it with
932 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
933 * e.g. Naitve DSD or Headphone 44.1 -> + 48
934 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530935static void check_and_set_asrc_mode(struct audio_device *adev,
936 struct audio_usecase *uc_info,
937 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530938{
939 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530940 int i, num_new_devices = 0;
941 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
942 /*
943 *Split snd device for new combo use case
944 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
945 */
946 if (platform_split_snd_device(adev->platform,
947 snd_device,
948 &num_new_devices,
949 split_new_snd_devices) == 0) {
950 for (i = 0; i < num_new_devices; i++)
951 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
952 } else {
953 int new_backend_idx = platform_get_backend_index(snd_device);
954 if (((new_backend_idx == HEADPHONE_BACKEND) ||
955 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
956 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
957 !adev->asrc_mode_enabled) {
958 struct listnode *node = NULL;
959 struct audio_usecase *uc = NULL;
960 struct stream_out *curr_out = NULL;
961 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
962 int i, num_devices, ret = 0;
963 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530964
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530965 list_for_each(node, &adev->usecase_list) {
966 uc = node_to_item(node, struct audio_usecase, list);
967 curr_out = (struct stream_out*) uc->stream.out;
968 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
969 /*
970 *Split snd device for existing combo use case
971 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
972 */
973 ret = platform_split_snd_device(adev->platform,
974 uc->out_snd_device,
975 &num_devices,
976 split_snd_devices);
977 if (ret < 0 || num_devices == 0) {
978 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
979 split_snd_devices[0] = uc->out_snd_device;
980 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800981 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530982 for (i = 0; i < num_devices; i++) {
983 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
984 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
985 if((new_backend_idx == HEADPHONE_BACKEND) &&
986 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
987 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
988 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
989 __func__);
990 enable_asrc_mode(adev);
991 break;
992 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
993 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
994 (usecase_backend_idx == HEADPHONE_BACKEND)) {
995 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
996 __func__);
997 disable_audio_route(adev, uc);
998 disable_snd_device(adev, uc->out_snd_device);
999 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1000 if (new_backend_idx == DSD_NATIVE_BACKEND)
1001 audio_route_apply_and_update_path(adev->audio_route,
1002 "hph-true-highquality-mode");
1003 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1004 (curr_out->bit_width >= 24))
1005 audio_route_apply_and_update_path(adev->audio_route,
1006 "hph-highquality-mode");
1007 enable_asrc_mode(adev);
1008 enable_snd_device(adev, uc->out_snd_device);
1009 enable_audio_route(adev, uc);
1010 break;
1011 }
1012 }
1013 // reset split devices count
1014 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001015 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301016 if (adev->asrc_mode_enabled)
1017 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301018 }
1019 }
1020 }
1021}
1022
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001023static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1024 struct audio_effect_config effect_config,
1025 unsigned int param_value)
1026{
1027 char mixer_ctl_name[] = "Audio Effect";
1028 struct mixer_ctl *ctl;
1029 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001030 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001031
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001032 if (in == NULL) {
1033 ALOGE("%s: active input stream is NULL", __func__);
1034 return -EINVAL;
1035 }
1036
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001037 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1038 if (!ctl) {
1039 ALOGE("%s: Could not get mixer ctl - %s",
1040 __func__, mixer_ctl_name);
1041 return -EINVAL;
1042 }
1043
1044 set_values[0] = 1; //0:Rx 1:Tx
1045 set_values[1] = in->app_type_cfg.app_type;
1046 set_values[2] = (long)effect_config.module_id;
1047 set_values[3] = (long)effect_config.instance_id;
1048 set_values[4] = (long)effect_config.param_id;
1049 set_values[5] = param_value;
1050
1051 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1052
1053 return 0;
1054
1055}
1056
1057static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1058 int effect_type, unsigned int *param_value)
1059{
1060 int ret = 0;
1061 struct audio_effect_config other_effect_config;
1062 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001063 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001064
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001065 if (in == NULL) {
1066 ALOGE("%s: active input stream is NULL", __func__);
1067 return -EINVAL;
1068 }
1069
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001070 usecase = get_usecase_from_list(adev, in->usecase);
1071 if (!usecase)
1072 return -EINVAL;
1073
1074 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1075 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1076 if (ret < 0) {
1077 ALOGE("%s Failed to get effect params %d", __func__, ret);
1078 return ret;
1079 }
1080
1081 if (module_id == other_effect_config.module_id) {
1082 //Same module id for AEC/NS. Values need to be combined
1083 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1084 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1085 *param_value |= other_effect_config.param_value;
1086 }
1087 }
1088
1089 return ret;
1090}
1091
1092static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301093{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001094 struct audio_effect_config effect_config;
1095 struct audio_usecase *usecase = NULL;
1096 int ret = 0;
1097 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001098 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001099
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001100 if(!voice_extn_is_dynamic_ecns_enabled())
1101 return ENOSYS;
1102
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001103 if (!in) {
1104 ALOGE("%s: Invalid input stream", __func__);
1105 return -EINVAL;
1106 }
1107
1108 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1109
1110 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001111 if (usecase == NULL) {
1112 ALOGE("%s: Could not find the usecase (%d) in the list",
1113 __func__, in->usecase);
1114 return -EINVAL;
1115 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001116
1117 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1118 if (ret < 0) {
1119 ALOGE("%s Failed to get module id %d", __func__, ret);
1120 return ret;
1121 }
1122 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1123 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1124
1125 if(enable)
1126 param_value = effect_config.param_value;
1127
1128 /*Special handling for AEC & NS effects Param values need to be
1129 updated if module ids are same*/
1130
1131 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1132 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1133 if (ret < 0)
1134 return ret;
1135 }
1136
1137 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1138
1139 return ret;
1140}
1141
1142static void check_and_enable_effect(struct audio_device *adev)
1143{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001144 if(!voice_extn_is_dynamic_ecns_enabled())
1145 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001146
Eric Laurent637e2d42018-11-15 12:24:31 -08001147 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001148
Eric Laurent637e2d42018-11-15 12:24:31 -08001149 if (in != NULL && !in->standby) {
1150 if (in->enable_aec)
1151 enable_disable_effect(adev, EFFECT_AEC, true);
1152
1153 if (in->enable_ns &&
1154 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1155 enable_disable_effect(adev, EFFECT_NS, true);
1156 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001157 }
1158}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001159
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001160int pcm_ioctl(struct pcm *pcm, int request, ...)
1161{
1162 va_list ap;
1163 void * arg;
1164 int pcm_fd = *(int*)pcm;
1165
1166 va_start(ap, request);
1167 arg = va_arg(ap, void *);
1168 va_end(ap);
1169
1170 return ioctl(pcm_fd, request, arg);
1171}
1172
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001173int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001174 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001175{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001176 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001177 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301178 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301179 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001180 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301181 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001182
1183 if (usecase == NULL)
1184 return -EINVAL;
1185
1186 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1187
Carter Hsu2e429db2019-05-14 18:50:52 +08001188 if (usecase->type == PCM_CAPTURE) {
1189 struct stream_in *in = usecase->stream.in;
1190 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001191 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001192
1193 if (in) {
1194 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001195 list_init(&out_devices);
1196 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001197 struct listnode *node;
1198 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1199 USECASE_AUDIO_PLAYBACK_VOIP);
1200 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001201 assign_devices(&out_devices,
1202 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001203 } else if (adev->primary_output &&
1204 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001205 assign_devices(&out_devices,
1206 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001207 } else {
1208 list_for_each(node, &adev->usecase_list) {
1209 uinfo = node_to_item(node, struct audio_usecase, list);
1210 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001211 assign_devices(&out_devices,
1212 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001213 break;
1214 }
1215 }
1216 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001217
1218 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001219 in->ec_opened = true;
1220 }
1221 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001222 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1223 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1224 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001225 snd_device = usecase->in_snd_device;
1226 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001227 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001228 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001229
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001230#ifdef DS1_DOLBY_DAP_ENABLED
1231 audio_extn_dolby_set_dmid(adev);
1232 audio_extn_dolby_set_endpoint(adev);
1233#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001234 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001235 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301236 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001237 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001238 if (audio_extn_is_maxx_audio_enabled())
1239 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301240 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301241 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1242 out = usecase->stream.out;
1243 if (out && out->compr)
1244 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1245 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301246
1247 if (usecase->type == PCM_CAPTURE) {
1248 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001249 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301250 ALOGD("%s: set custom mtmx params v1", __func__);
1251 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1252 }
1253 } else {
1254 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1255 }
Manish Dewangan58229382017-02-02 15:48:41 +05301256
Andy Hung756ecc12018-10-19 17:47:12 -07001257 // we shouldn't truncate mixer_path
1258 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1259 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1260 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001261 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001262 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301263 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1264 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1265 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1266 if (parms) {
1267 audio_extn_fm_set_parameters(adev, parms);
1268 str_parms_destroy(parms);
1269 }
1270 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271 ALOGV("%s: exit", __func__);
1272 return 0;
1273}
1274
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001275int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001276 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001278 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001279 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301280 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001281
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301282 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001283 return -EINVAL;
1284
1285 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301286 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001287 snd_device = usecase->in_snd_device;
1288 else
1289 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001290 // we shouldn't truncate mixer_path
1291 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1292 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1293 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001294 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001295 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001296 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001297 if (usecase->type == PCM_CAPTURE) {
1298 struct stream_in *in = usecase->stream.in;
1299 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001300 struct listnode out_devices;
1301 list_init(&out_devices);
1302 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001303 in->ec_opened = false;
1304 }
1305 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001306 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301307 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301308
1309 if (usecase->type == PCM_CAPTURE) {
1310 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001311 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301312 ALOGD("%s: reset custom mtmx params v1", __func__);
1313 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1314 }
1315 } else {
1316 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1317 }
1318
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001319 if ((usecase->type == PCM_PLAYBACK) &&
1320 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301321 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001323 ALOGV("%s: exit", __func__);
1324 return 0;
1325}
1326
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001327int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001328 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001329{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301330 int i, num_devices = 0;
1331 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001332 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1333
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001334 if (snd_device < SND_DEVICE_MIN ||
1335 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001336 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001337 return -EINVAL;
1338 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001339
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001340 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001341 ALOGE("%s: Invalid sound device returned", __func__);
1342 return -EINVAL;
1343 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001344
1345 adev->snd_dev_ref_cnt[snd_device]++;
1346
1347 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1348 (platform_split_snd_device(adev->platform,
1349 snd_device,
1350 &num_devices,
1351 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001352 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001353 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001354 return 0;
1355 }
1356
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001357 if (audio_extn_spkr_prot_is_enabled())
1358 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001359
Aalique Grahame22e49102018-12-18 14:23:57 -08001360 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1361
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001362 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1363 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001364 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1365 goto err;
1366 }
1367 audio_extn_dev_arbi_acquire(snd_device);
1368 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001369 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001370 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001371 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001372 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001373 } else if (platform_split_snd_device(adev->platform,
1374 snd_device,
1375 &num_devices,
1376 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301377 for (i = 0; i < num_devices; i++) {
1378 enable_snd_device(adev, new_snd_devices[i]);
1379 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001380 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001381 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001382 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301383
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301384
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001385 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1386 (audio_extn_a2dp_start_playback() < 0)) {
1387 ALOGE(" fail to configure A2dp Source control path ");
1388 goto err;
1389 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001390
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001391 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1392 (audio_extn_a2dp_start_capture() < 0)) {
1393 ALOGE(" fail to configure A2dp Sink control path ");
1394 goto err;
1395 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301396
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001397 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1398 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1399 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1400 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1401 ALOGE(" fail to configure sco control path ");
1402 goto err;
1403 }
Zhou Song12c29502019-03-16 10:37:18 +08001404 }
1405
Zhou Song331c8e52019-08-26 14:16:12 +08001406 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001407 /* due to the possibility of calibration overwrite between listen
1408 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001409 audio_extn_sound_trigger_update_device_status(snd_device,
1410 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301411 audio_extn_listen_update_device_status(snd_device,
1412 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001413 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001414 audio_extn_sound_trigger_update_device_status(snd_device,
1415 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301416 audio_extn_listen_update_device_status(snd_device,
1417 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001418 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001419 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001420 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001421 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301422
1423 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1424 !adev->native_playback_enabled &&
1425 audio_is_true_native_stream_active(adev)) {
1426 ALOGD("%s: %d: napb: enabling native mode in hardware",
1427 __func__, __LINE__);
1428 audio_route_apply_and_update_path(adev->audio_route,
1429 "true-native-mode");
1430 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301431 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301432 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1433 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001434 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001435 ALOGD("%s: init ec ref loopback", __func__);
1436 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1437 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001439 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001440err:
1441 adev->snd_dev_ref_cnt[snd_device]--;
1442 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443}
1444
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001445int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001446 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001447{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301448 int i, num_devices = 0;
1449 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001450 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1451
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001452 if (snd_device < SND_DEVICE_MIN ||
1453 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001454 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001455 return -EINVAL;
1456 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001457
1458 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1459 ALOGE("%s: Invalid sound device returned", __func__);
1460 return -EINVAL;
1461 }
1462
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001463 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1464 ALOGE("%s: device ref cnt is already 0", __func__);
1465 return -EINVAL;
1466 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001467
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001468 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001469
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001470
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001471 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001472 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301473
Aalique Grahame22e49102018-12-18 14:23:57 -08001474 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1475
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001476 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1477 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001478 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001479
1480 // when speaker device is disabled, reset swap.
1481 // will be renabled on usecase start
1482 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001483 } else if (platform_split_snd_device(adev->platform,
1484 snd_device,
1485 &num_devices,
1486 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301487 for (i = 0; i < num_devices; i++) {
1488 disable_snd_device(adev, new_snd_devices[i]);
1489 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001490 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001491 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001492 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001493 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001494
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001495 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301496 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001497 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001498 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001499 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001500 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301501 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001502 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301503 adev->native_playback_enabled) {
1504 ALOGD("%s: %d: napb: disabling native mode in hardware",
1505 __func__, __LINE__);
1506 audio_route_reset_and_update_path(adev->audio_route,
1507 "true-native-mode");
1508 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001509 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301510 adev->asrc_mode_enabled) {
1511 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301512 disable_asrc_mode(adev);
1513 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001514 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301515 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001516 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001517 ALOGD("%s: deinit ec ref loopback", __func__);
1518 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1519 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001520
1521 audio_extn_utils_release_snd_device(snd_device);
1522 } else {
1523 if (platform_split_snd_device(adev->platform,
1524 snd_device,
1525 &num_devices,
1526 new_snd_devices) == 0) {
1527 for (i = 0; i < num_devices; i++) {
1528 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1529 }
1530 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001531 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533 return 0;
1534}
1535
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001536/*
1537 legend:
1538 uc - existing usecase
1539 new_uc - new usecase
1540 d1, d11, d2 - SND_DEVICE enums
1541 a1, a2 - corresponding ANDROID device enums
1542 B1, B2 - backend strings
1543
1544case 1
1545 uc->dev d1 (a1) B1
1546 new_uc->dev d1 (a1), d2 (a2) B1, B2
1547
1548 resolution: disable and enable uc->dev on d1
1549
1550case 2
1551 uc->dev d1 (a1) B1
1552 new_uc->dev d11 (a1) B1
1553
1554 resolution: need to switch uc since d1 and d11 are related
1555 (e.g. speaker and voice-speaker)
1556 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1557
1558case 3
1559 uc->dev d1 (a1) B1
1560 new_uc->dev d2 (a2) B2
1561
1562 resolution: no need to switch uc
1563
1564case 4
1565 uc->dev d1 (a1) B1
1566 new_uc->dev d2 (a2) B1
1567
1568 resolution: disable enable uc-dev on d2 since backends match
1569 we cannot enable two streams on two different devices if they
1570 share the same backend. e.g. if offload is on speaker device using
1571 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1572 using the same backend, offload must also be switched to voice-handset.
1573
1574case 5
1575 uc->dev d1 (a1) B1
1576 new_uc->dev d1 (a1), d2 (a2) B1
1577
1578 resolution: disable enable uc-dev on d2 since backends match
1579 we cannot enable two streams on two different devices if they
1580 share the same backend.
1581
1582case 6
1583 uc->dev d1 (a1) B1
1584 new_uc->dev d2 (a1) B2
1585
1586 resolution: no need to switch
1587
1588case 7
1589 uc->dev d1 (a1), d2 (a2) B1, B2
1590 new_uc->dev d1 (a1) B1
1591
1592 resolution: no need to switch
1593
Zhou Song4ba65882018-07-09 14:48:07 +08001594case 8
1595 uc->dev d1 (a1) B1
1596 new_uc->dev d11 (a1), d2 (a2) B1, B2
1597 resolution: compared to case 1, for this case, d1 and d11 are related
1598 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001599*/
1600static snd_device_t derive_playback_snd_device(void * platform,
1601 struct audio_usecase *uc,
1602 struct audio_usecase *new_uc,
1603 snd_device_t new_snd_device)
1604{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001605 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001606
1607 snd_device_t d1 = uc->out_snd_device;
1608 snd_device_t d2 = new_snd_device;
1609
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001610 list_init(&a1);
1611 list_init(&a2);
1612
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301613 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301614 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001615 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1616 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301617 break;
1618 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001619 assign_devices(&a1, &uc->stream.out->device_list);
1620 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301621 break;
1622 }
1623
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001624 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001625 if (!compare_devices(&a1, &a2) &&
1626 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001627 snd_device_t d3[2];
1628 int num_devices = 0;
1629 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001630 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001631 &num_devices,
1632 d3);
1633 if (ret < 0) {
1634 if (ret != -ENOSYS) {
1635 ALOGW("%s failed to split snd_device %d",
1636 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001637 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001638 }
1639 goto end;
1640 }
1641
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001642 if (platform_check_backends_match(d3[0], d3[1])) {
1643 return d2; // case 5
1644 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001645 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301646 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001647 // check if d1 is related to any of d3's
1648 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001649 return d1; // case 1
1650 else
1651 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001652 }
1653 } else {
1654 if (platform_check_backends_match(d1, d2)) {
1655 return d2; // case 2, 4
1656 } else {
1657 return d1; // case 6, 3
1658 }
1659 }
1660
1661end:
1662 return d2; // return whatever was calculated before.
1663}
1664
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001665static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301666 struct audio_usecase *uc_info,
1667 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001668{
1669 struct listnode *node;
1670 struct audio_usecase *usecase;
1671 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301672 snd_device_t uc_derive_snd_device;
1673 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001674 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1675 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001676 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301677 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001678 /*
1679 * This function is to make sure that all the usecases that are active on
1680 * the hardware codec backend are always routed to any one device that is
1681 * handled by the hardware codec.
1682 * For example, if low-latency and deep-buffer usecases are currently active
1683 * on speaker and out_set_parameters(headset) is received on low-latency
1684 * output, then we have to make sure deep-buffer is also switched to headset,
1685 * because of the limitation that both the devices cannot be enabled
1686 * at the same time as they share the same backend.
1687 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001688 /*
1689 * This call is to check if we need to force routing for a particular stream
1690 * If there is a backend configuration change for the device when a
1691 * new stream starts, then ADM needs to be closed and re-opened with the new
1692 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001693 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001694 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001695 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1696 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301697 /* For a2dp device reconfigure all active sessions
1698 * with new AFE encoder format based on a2dp state
1699 */
1700 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1701 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1702 audio_extn_a2dp_is_force_device_switch()) {
1703 force_routing = true;
1704 force_restart_session = true;
1705 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301706 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1707
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001708 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001709 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001710 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001711 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1712 switch_device[i] = false;
1713
1714 list_for_each(node, &adev->usecase_list) {
1715 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001716
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301717 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1718 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301719 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301720 platform_get_snd_device_name(usecase->out_snd_device),
1721 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301722 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1723 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301724 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1725 usecase, uc_info, snd_device);
1726 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001727 (is_codec_backend_out_device_type(&usecase->device_list) ||
1728 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1729 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1730 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1731 is_a2dp_out_device_type(&usecase->device_list) ||
1732 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301733 ((force_restart_session) ||
1734 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301735 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1736 __func__, use_case_table[usecase->id],
1737 platform_get_snd_device_name(usecase->out_snd_device));
1738 disable_audio_route(adev, usecase);
1739 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301740 /* Enable existing usecase on derived playback device */
1741 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301742 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301743 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001744 }
1745 }
1746
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301747 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1748 num_uc_to_switch);
1749
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001750 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001751 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001752
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301753 /* Make sure the previous devices to be disabled first and then enable the
1754 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001755 list_for_each(node, &adev->usecase_list) {
1756 usecase = node_to_item(node, struct audio_usecase, list);
1757 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001758 /* Check if output sound device to be switched can be split and if any
1759 of the split devices match with derived sound device */
1760 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1761 &num_devices, split_snd_devices) == 0) {
1762 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1763 for (i = 0; i < num_devices; i++) {
1764 /* Disable devices that do not match with derived sound device */
1765 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1766 disable_snd_device(adev, split_snd_devices[i]);
1767 }
1768 } else {
1769 disable_snd_device(adev, usecase->out_snd_device);
1770 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001771 }
1772 }
1773
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001774 list_for_each(node, &adev->usecase_list) {
1775 usecase = node_to_item(node, struct audio_usecase, list);
1776 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001777 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1778 &num_devices, split_snd_devices) == 0) {
1779 /* Enable derived sound device only if it does not match with
1780 one of the split sound devices. This is because the matching
1781 sound device was not disabled */
1782 bool should_enable = true;
1783 for (i = 0; i < num_devices; i++) {
1784 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1785 should_enable = false;
1786 break;
1787 }
1788 }
1789 if (should_enable)
1790 enable_snd_device(adev, derive_snd_device[usecase->id]);
1791 } else {
1792 enable_snd_device(adev, derive_snd_device[usecase->id]);
1793 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001794 }
1795 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001796
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001797 /* Re-route all the usecases on the shared backend other than the
1798 specified usecase to new snd devices */
1799 list_for_each(node, &adev->usecase_list) {
1800 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301801 /* Update the out_snd_device only before enabling the audio route */
1802 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301803 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301804 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301805 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301806 use_case_table[usecase->id],
1807 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001808 /* Update voc calibration before enabling VoIP route */
1809 if (usecase->type == VOIP_CALL)
1810 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001811 usecase->out_snd_device,
1812 platform_get_input_snd_device(
1813 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301814 &uc_info->device_list,
1815 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301816 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301817 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001818 out_set_voip_volume(&usecase->stream.out->stream,
1819 usecase->stream.out->volume_l,
1820 usecase->stream.out->volume_r);
1821 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301822 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001823 }
1824 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001825 }
1826}
1827
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301828static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001829 struct audio_usecase *uc_info,
1830 snd_device_t snd_device)
1831{
1832 struct listnode *node;
1833 struct audio_usecase *usecase;
1834 bool switch_device[AUDIO_USECASE_MAX];
1835 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001836 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001837 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001838
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301839 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1840 snd_device);
1841 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301842
1843 /*
1844 * Make sure out devices is checked against out codec backend device and
1845 * also in devices against in codec backend. Checking out device against in
1846 * codec backend or vice versa causes issues.
1847 */
1848 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001849 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001850 /*
1851 * This function is to make sure that all the active capture usecases
1852 * are always routed to the same input sound device.
1853 * For example, if audio-record and voice-call usecases are currently
1854 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1855 * is received for voice call then we have to make sure that audio-record
1856 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1857 * because of the limitation that two devices cannot be enabled
1858 * at the same time if they share the same backend.
1859 */
1860 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1861 switch_device[i] = false;
1862
1863 list_for_each(node, &adev->usecase_list) {
1864 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301865 /*
1866 * TODO: Enhance below condition to handle BT sco/USB multi recording
1867 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301868
1869 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1870 (usecase->in_snd_device != snd_device || force_routing));
1871 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1872 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1873 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001874 ((backend_check_cond &&
1875 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001876 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001877 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001878 is_single_device_type_equal(&usecase->device_list,
1879 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001880 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001881 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001882 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301883 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001884 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001885 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001886 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001887 switch_device[usecase->id] = true;
1888 num_uc_to_switch++;
1889 }
1890 }
1891
1892 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001893 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001894
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301895 /* Make sure the previous devices to be disabled first and then enable the
1896 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001897 list_for_each(node, &adev->usecase_list) {
1898 usecase = node_to_item(node, struct audio_usecase, list);
1899 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001900 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001901 }
1902 }
1903
1904 list_for_each(node, &adev->usecase_list) {
1905 usecase = node_to_item(node, struct audio_usecase, list);
1906 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001907 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001908 }
1909 }
1910
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001911 /* Re-route all the usecases on the shared backend other than the
1912 specified usecase to new snd devices */
1913 list_for_each(node, &adev->usecase_list) {
1914 usecase = node_to_item(node, struct audio_usecase, list);
1915 /* Update the in_snd_device only before enabling the audio route */
1916 if (switch_device[usecase->id] ) {
1917 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001918 if (usecase->type != VOICE_CALL) {
1919 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301920 if (usecase->type == VOIP_CALL) {
1921 snd_device_t voip_snd_device;
1922 voip_snd_device = platform_get_output_snd_device(adev->platform,
1923 uc_info->stream.out,
1924 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08001925 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301926 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08001927 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05301928 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05301929 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001930 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001931 }
1932 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001933 }
1934}
1935
Mingming Yin3a941d42016-02-17 18:08:05 -08001936static void reset_hdmi_sink_caps(struct stream_out *out) {
1937 int i = 0;
1938
1939 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1940 out->supported_channel_masks[i] = 0;
1941 }
1942 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1943 out->supported_formats[i] = 0;
1944 }
1945 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1946 out->supported_sample_rates[i] = 0;
1947 }
1948}
1949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001951static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952{
Mingming Yin3a941d42016-02-17 18:08:05 -08001953 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001954 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
1955 out->extconn.cs.controller,
1956 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001957
Mingming Yin3a941d42016-02-17 18:08:05 -08001958 reset_hdmi_sink_caps(out);
1959
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001960 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08001961 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001962 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08001963 out->extconn.cs.stream);
1964 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001965 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001966 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001967 }
1968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001971 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001972 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001973 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1974 case 6:
1975 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1976 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1977 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1978 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1979 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1980 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981 break;
1982 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001983 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001984 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001985 break;
1986 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001987
1988 // check channel format caps
1989 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001990 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
1991 out->extconn.cs.controller,
1992 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08001993 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1994 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1995 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1996 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1997 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1998 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1999 }
2000
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002001 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2002 out->extconn.cs.controller,
2003 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002004 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2005 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2006 }
2007
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002008 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2009 out->extconn.cs.controller,
2010 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002011 ALOGV(":%s HDMI supports DTS format", __func__);
2012 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2013 }
2014
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002015 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2016 out->extconn.cs.controller,
2017 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002018 ALOGV(":%s HDMI supports DTS HD format", __func__);
2019 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2020 }
2021
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002022 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2023 out->extconn.cs.controller,
2024 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002025 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2026 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2027 }
2028
Mingming Yin3a941d42016-02-17 18:08:05 -08002029
2030 // check sample rate caps
2031 i = 0;
2032 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002033 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2034 out->extconn.cs.controller,
2035 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002036 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2037 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2038 }
2039 }
2040
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002041 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042}
2043
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002044static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2045 uint32_t *supported_sample_rates __unused,
2046 uint32_t max_rates __unused)
2047{
2048 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2049 supported_sample_rates,
2050 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302051 ssize_t i = 0;
2052
2053 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002054 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2055 supported_sample_rates[i]);
2056 }
2057 return count;
2058}
2059
2060static inline int read_usb_sup_channel_masks(bool is_playback,
2061 audio_channel_mask_t *supported_channel_masks,
2062 uint32_t max_masks)
2063{
2064 int channels = audio_extn_usb_get_max_channels(is_playback);
2065 int channel_count;
2066 uint32_t num_masks = 0;
2067 if (channels > MAX_HIFI_CHANNEL_COUNT)
2068 channels = MAX_HIFI_CHANNEL_COUNT;
2069
2070 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002071 // start from 2 channels as framework currently doesn't support mono.
2072 if (channels >= FCC_2) {
2073 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2074 }
2075 for (channel_count = FCC_2;
2076 channel_count <= channels && num_masks < max_masks;
2077 ++channel_count) {
2078 supported_channel_masks[num_masks++] =
2079 audio_channel_mask_for_index_assignment_from_count(channel_count);
2080 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002081 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002082 // For capture we report all supported channel masks from 1 channel up.
2083 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002084 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2085 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002086 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2087 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2088 if (channel_count <= FCC_2) {
2089 mask = audio_channel_in_mask_from_count(channel_count);
2090 supported_channel_masks[num_masks++] = mask;
2091 }
2092 const audio_channel_mask_t index_mask =
2093 audio_channel_mask_for_index_assignment_from_count(channel_count);
2094 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2095 supported_channel_masks[num_masks++] = index_mask;
2096 }
2097 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002098 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302099
vincenttewf51c94e2019-05-07 10:28:53 +08002100 for (size_t i = 0; i < num_masks; ++i) {
2101 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2102 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302103 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002104 return num_masks;
2105}
2106
2107static inline int read_usb_sup_formats(bool is_playback __unused,
2108 audio_format_t *supported_formats,
2109 uint32_t max_formats __unused)
2110{
2111 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2112 switch (bitwidth) {
2113 case 24:
2114 // XXX : usb.c returns 24 for s24 and s24_le?
2115 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2116 break;
2117 case 32:
2118 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2119 break;
2120 case 16:
2121 default :
2122 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2123 break;
2124 }
2125 ALOGV("%s: %s supported format %d", __func__,
2126 is_playback ? "P" : "C", bitwidth);
2127 return 1;
2128}
2129
2130static inline int read_usb_sup_params_and_compare(bool is_playback,
2131 audio_format_t *format,
2132 audio_format_t *supported_formats,
2133 uint32_t max_formats,
2134 audio_channel_mask_t *mask,
2135 audio_channel_mask_t *supported_channel_masks,
2136 uint32_t max_masks,
2137 uint32_t *rate,
2138 uint32_t *supported_sample_rates,
2139 uint32_t max_rates) {
2140 int ret = 0;
2141 int num_formats;
2142 int num_masks;
2143 int num_rates;
2144 int i;
2145
2146 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2147 max_formats);
2148 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2149 max_masks);
2150
2151 num_rates = read_usb_sup_sample_rates(is_playback,
2152 supported_sample_rates, max_rates);
2153
2154#define LUT(table, len, what, dflt) \
2155 for (i=0; i<len && (table[i] != what); i++); \
2156 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2157
2158 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2159 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2160 LUT(supported_sample_rates, num_rates, *rate, 0);
2161
2162#undef LUT
2163 return ret < 0 ? -EINVAL : 0; // HACK TBD
2164}
2165
Alexy Josephb1379942016-01-29 15:49:38 -08002166audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002167 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002168{
2169 struct audio_usecase *usecase;
2170 struct listnode *node;
2171
2172 list_for_each(node, &adev->usecase_list) {
2173 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002174 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002175 ALOGV("%s: usecase id %d", __func__, usecase->id);
2176 return usecase->id;
2177 }
2178 }
2179 return USECASE_INVALID;
2180}
2181
Alexy Josephb1379942016-01-29 15:49:38 -08002182struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002183 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002184{
2185 struct audio_usecase *usecase;
2186 struct listnode *node;
2187
2188 list_for_each(node, &adev->usecase_list) {
2189 usecase = node_to_item(node, struct audio_usecase, list);
2190 if (usecase->id == uc_id)
2191 return usecase;
2192 }
2193 return NULL;
2194}
2195
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302196/*
2197 * is a true native playback active
2198 */
2199bool audio_is_true_native_stream_active(struct audio_device *adev)
2200{
2201 bool active = false;
2202 int i = 0;
2203 struct listnode *node;
2204
2205 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2206 ALOGV("%s:napb: not in true mode or non hdphones device",
2207 __func__);
2208 active = false;
2209 goto exit;
2210 }
2211
2212 list_for_each(node, &adev->usecase_list) {
2213 struct audio_usecase *uc;
2214 uc = node_to_item(node, struct audio_usecase, list);
2215 struct stream_out *curr_out =
2216 (struct stream_out*) uc->stream.out;
2217
2218 if (curr_out && PCM_PLAYBACK == uc->type) {
2219 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2220 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2221 uc->id, curr_out->sample_rate,
2222 curr_out->bit_width,
2223 platform_get_snd_device_name(uc->out_snd_device));
2224
2225 if (is_offload_usecase(uc->id) &&
2226 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2227 active = true;
2228 ALOGD("%s:napb:native stream detected", __func__);
2229 }
2230 }
2231 }
2232exit:
2233 return active;
2234}
2235
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002236uint32_t adev_get_dsp_bit_width_enforce_mode()
2237{
2238 if (adev == NULL) {
2239 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2240 return 0;
2241 }
2242 return adev->dsp_bit_width_enforce_mode;
2243}
2244
2245static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2246{
2247 char value[PROPERTY_VALUE_MAX];
2248 int trial;
2249 uint32_t dsp_bit_width_enforce_mode = 0;
2250
2251 if (!mixer) {
2252 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2253 __func__);
2254 return 0;
2255 }
2256
2257 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2258 value, NULL) > 0) {
2259 trial = atoi(value);
2260 switch (trial) {
2261 case 16:
2262 dsp_bit_width_enforce_mode = 16;
2263 break;
2264 case 24:
2265 dsp_bit_width_enforce_mode = 24;
2266 break;
2267 case 32:
2268 dsp_bit_width_enforce_mode = 32;
2269 break;
2270 default:
2271 dsp_bit_width_enforce_mode = 0;
2272 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2273 break;
2274 }
2275 }
2276
2277 return dsp_bit_width_enforce_mode;
2278}
2279
2280static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2281 uint32_t enforce_mode,
2282 bool enable)
2283{
2284 struct mixer_ctl *ctl = NULL;
2285 const char *mixer_ctl_name = "ASM Bit Width";
2286 uint32_t asm_bit_width_mode = 0;
2287
2288 if (enforce_mode == 0) {
2289 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2290 return;
2291 }
2292
2293 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2294 if (!ctl) {
2295 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2296 __func__, mixer_ctl_name);
2297 return;
2298 }
2299
2300 if (enable)
2301 asm_bit_width_mode = enforce_mode;
2302 else
2303 asm_bit_width_mode = 0;
2304
2305 ALOGV("%s DSP bit width feature status is %d width=%d",
2306 __func__, enable, asm_bit_width_mode);
2307 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2308 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2309 asm_bit_width_mode);
2310
2311 return;
2312}
2313
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302314/*
2315 * if native DSD playback active
2316 */
2317bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2318{
2319 bool active = false;
2320 struct listnode *node = NULL;
2321 struct audio_usecase *uc = NULL;
2322 struct stream_out *curr_out = NULL;
2323
2324 list_for_each(node, &adev->usecase_list) {
2325 uc = node_to_item(node, struct audio_usecase, list);
2326 curr_out = (struct stream_out*) uc->stream.out;
2327
2328 if (curr_out && PCM_PLAYBACK == uc->type &&
2329 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2330 active = true;
2331 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302332 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302333 }
2334 }
2335 return active;
2336}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302337
2338static bool force_device_switch(struct audio_usecase *usecase)
2339{
2340 bool ret = false;
2341 bool is_it_true_mode = false;
2342
Zhou Song30f2c3e2018-02-08 14:02:15 +08002343 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302344 usecase->type == TRANSCODE_LOOPBACK_RX ||
2345 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002346 return false;
2347 }
2348
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002349 if(usecase->stream.out == NULL) {
2350 ALOGE("%s: stream.out is NULL", __func__);
2351 return false;
2352 }
2353
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302354 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002355 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002356 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2357 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302358 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2359 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2360 (!is_it_true_mode && adev->native_playback_enabled)){
2361 ret = true;
2362 ALOGD("napb: time to toggle native mode");
2363 }
2364 }
2365
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302366 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302367 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2368 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002369 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302370 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302371 ALOGD("Force a2dp device switch to update new encoder config");
2372 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002373 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302374
Florian Pfister1a84f312018-07-19 14:38:18 +02002375 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302376 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2377 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002378 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302379 return ret;
2380}
2381
Aalique Grahame22e49102018-12-18 14:23:57 -08002382static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2383{
2384 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2385}
2386
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302387bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2388{
2389 bool ret=false;
2390 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002391 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2392 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302393 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2394 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002395 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302396 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002397 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2398 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302399 ret = true;
2400
2401 return ret;
2402}
2403
2404bool is_a2dp_device(snd_device_t out_snd_device)
2405{
2406 bool ret=false;
2407 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2408 ret = true;
2409
2410 return ret;
2411}
2412
2413bool is_bt_soc_on(struct audio_device *adev)
2414{
2415 struct mixer_ctl *ctl;
2416 char *mixer_ctl_name = "BT SOC status";
2417 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2418 bool bt_soc_status = true;
2419 if (!ctl) {
2420 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2421 __func__, mixer_ctl_name);
2422 /*This is to ensure we dont break targets which dont have the kernel change*/
2423 return true;
2424 }
2425 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2426 ALOGD("BT SOC status: %d",bt_soc_status);
2427 return bt_soc_status;
2428}
2429
Zhou Song331c8e52019-08-26 14:16:12 +08002430static int configure_btsco_sample_rate(snd_device_t snd_device)
2431{
2432 struct mixer_ctl *ctl = NULL;
2433 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2434 char *rate_str = NULL;
2435 bool is_rx_dev = true;
2436
2437 if (is_btsco_device(snd_device, snd_device)) {
2438 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2439 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2440 if (!ctl_sr_tx || !ctl_sr_rx) {
2441 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2442 if (!ctl_sr)
2443 return -ENOSYS;
2444 }
2445
2446 switch (snd_device) {
2447 case SND_DEVICE_OUT_BT_SCO:
2448 rate_str = "KHZ_8";
2449 break;
2450 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2451 case SND_DEVICE_IN_BT_SCO_MIC:
2452 rate_str = "KHZ_8";
2453 is_rx_dev = false;
2454 break;
2455 case SND_DEVICE_OUT_BT_SCO_WB:
2456 rate_str = "KHZ_16";
2457 break;
2458 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2459 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2460 rate_str = "KHZ_16";
2461 is_rx_dev = false;
2462 break;
2463 default:
2464 return 0;
2465 }
2466
2467 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2468 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2469 return -ENOSYS;
2470 }
2471 return 0;
2472}
2473
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302474int out_standby_l(struct audio_stream *stream);
2475
Eric Laurent637e2d42018-11-15 12:24:31 -08002476struct stream_in *adev_get_active_input(const struct audio_device *adev)
2477{
2478 struct listnode *node;
2479 struct stream_in *last_active_in = NULL;
2480
2481 /* Get last added active input.
2482 * TODO: We may use a priority mechanism to pick highest priority active source */
2483 list_for_each(node, &adev->usecase_list)
2484 {
2485 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2486 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2487 last_active_in = usecase->stream.in;
2488 }
2489
2490 return last_active_in;
2491}
2492
2493struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2494{
2495 struct listnode *node;
2496
2497 /* First check active inputs with voice communication source and then
2498 * any input if audio mode is in communication */
2499 list_for_each(node, &adev->usecase_list)
2500 {
2501 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2502 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2503 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2504 return usecase->stream.in;
2505 }
2506 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2507 return adev_get_active_input(adev);
2508
2509 return NULL;
2510}
2511
Carter Hsu2e429db2019-05-14 18:50:52 +08002512/*
2513 * Aligned with policy.h
2514 */
2515static inline int source_priority(int inputSource)
2516{
2517 switch (inputSource) {
2518 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2519 return 9;
2520 case AUDIO_SOURCE_CAMCORDER:
2521 return 8;
2522 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2523 return 7;
2524 case AUDIO_SOURCE_UNPROCESSED:
2525 return 6;
2526 case AUDIO_SOURCE_MIC:
2527 return 5;
2528 case AUDIO_SOURCE_ECHO_REFERENCE:
2529 return 4;
2530 case AUDIO_SOURCE_FM_TUNER:
2531 return 3;
2532 case AUDIO_SOURCE_VOICE_RECOGNITION:
2533 return 2;
2534 case AUDIO_SOURCE_HOTWORD:
2535 return 1;
2536 default:
2537 break;
2538 }
2539 return 0;
2540}
2541
2542static struct stream_in *get_priority_input(struct audio_device *adev)
2543{
2544 struct listnode *node;
2545 struct audio_usecase *usecase;
2546 int last_priority = 0, priority;
2547 struct stream_in *priority_in = NULL;
2548 struct stream_in *in;
2549
2550 list_for_each(node, &adev->usecase_list) {
2551 usecase = node_to_item(node, struct audio_usecase, list);
2552 if (usecase->type == PCM_CAPTURE) {
2553 in = usecase->stream.in;
2554 if (!in)
2555 continue;
2556 priority = source_priority(in->source);
2557
2558 if (priority > last_priority) {
2559 last_priority = priority;
2560 priority_in = in;
2561 }
2562 }
2563 }
2564 return priority_in;
2565}
2566
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002567int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002569 snd_device_t out_snd_device = SND_DEVICE_NONE;
2570 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002571 struct audio_usecase *usecase = NULL;
2572 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002573 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002574 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302575 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002576 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002577 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302579 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2580
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002581 usecase = get_usecase_from_list(adev, uc_id);
2582 if (usecase == NULL) {
2583 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2584 return -EINVAL;
2585 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002587 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002588 (usecase->type == VOIP_CALL) ||
2589 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302590 if(usecase->stream.out == NULL) {
2591 ALOGE("%s: stream.out is NULL", __func__);
2592 return -EINVAL;
2593 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002594 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002595 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2596 uc_id);
2597 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2598 uc_id);
2599 } else {
2600 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302601 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002602 in_snd_device = platform_get_input_snd_device(adev->platform,
2603 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302604 &usecase->stream.out->device_list,
2605 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002606 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002607 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302608 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302609 if (usecase->stream.inout == NULL) {
2610 ALOGE("%s: stream.inout is NULL", __func__);
2611 return -EINVAL;
2612 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002613 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302614 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2615 stream_out.format = usecase->stream.inout->out_config.format;
2616 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302617 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002618 assign_devices(&usecase->device_list,
2619 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302620 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2621 if (usecase->stream.inout == NULL) {
2622 ALOGE("%s: stream.inout is NULL", __func__);
2623 return -EINVAL;
2624 }
Jaideep Sharma477917f2020-03-13 18:13:33 +05302625 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, NULL, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002626 assign_devices(&usecase->device_list,
2627 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002628 } else {
2629 /*
2630 * If the voice call is active, use the sound devices of voice call usecase
2631 * so that it would not result any device switch. All the usecases will
2632 * be switched to new device when select_devices() is called for voice call
2633 * usecase. This is to avoid switching devices for voice call when
2634 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002635 * choose voice call device only if the use case device is
2636 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002637 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002638 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002639 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002640 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002641 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2642 is_codec_backend_out_device_type(&usecase->device_list)) ||
2643 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2644 is_codec_backend_in_device_type(&usecase->device_list)) ||
2645 is_single_device_type_equal(&vc_usecase->device_list,
2646 AUDIO_DEVICE_OUT_HEARING_AID) ||
2647 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002648 AUDIO_DEVICE_IN_VOICE_CALL) ||
2649 (is_single_device_type_equal(&usecase->device_list,
2650 AUDIO_DEVICE_IN_USB_HEADSET) &&
2651 is_single_device_type_equal(&vc_usecase->device_list,
2652 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002653 in_snd_device = vc_usecase->in_snd_device;
2654 out_snd_device = vc_usecase->out_snd_device;
2655 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002656 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002657 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002658 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002659 if ((voip_usecase != NULL) &&
2660 (usecase->type == PCM_PLAYBACK) &&
2661 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002662 out_snd_device_backend_match = platform_check_backends_match(
2663 voip_usecase->out_snd_device,
2664 platform_get_output_snd_device(
2665 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302666 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002667 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002668 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2669 (is_codec_backend_out_device_type(&usecase->device_list) ||
2670 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002671 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002672 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002673 in_snd_device = voip_usecase->in_snd_device;
2674 out_snd_device = voip_usecase->out_snd_device;
2675 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002676 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002677 hfp_ucid = audio_extn_hfp_get_usecase();
2678 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002679 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002680 in_snd_device = hfp_usecase->in_snd_device;
2681 out_snd_device = hfp_usecase->out_snd_device;
2682 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002683 }
2684 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302685 if (usecase->stream.out == NULL) {
2686 ALOGE("%s: stream.out is NULL", __func__);
2687 return -EINVAL;
2688 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002689 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002690 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002691 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002692 struct stream_out *voip_out = adev->primary_output;
2693 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002694 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002695 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2696 else
2697 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302698 usecase->stream.out,
2699 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002700 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002701
Eric Laurent637e2d42018-11-15 12:24:31 -08002702 if (voip_usecase)
2703 voip_out = voip_usecase->stream.out;
2704
2705 if (usecase->stream.out == voip_out && voip_in != NULL)
2706 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002707 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002708 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302709 if (usecase->stream.in == NULL) {
2710 ALOGE("%s: stream.in is NULL", __func__);
2711 return -EINVAL;
2712 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002713 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002714 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002715 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002716 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002717 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002718 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002719
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002720 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002721 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002722 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2723 USECASE_AUDIO_PLAYBACK_VOIP);
2724
Carter Hsu2e429db2019-05-14 18:50:52 +08002725 usecase->stream.in->enable_ec_port = false;
2726
Eric Laurent637e2d42018-11-15 12:24:31 -08002727 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002728 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002729 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002730 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002731 } else if (adev->primary_output &&
2732 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002733 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002734 } else {
2735 /* forcing speaker o/p device to get matching i/p pair
2736 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002737 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002738 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002739 priority_in = voip_in;
2740 } else {
2741 /* get the input with the highest priority source*/
2742 priority_in = get_priority_input(adev);
2743
2744 if (!priority_in)
2745 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002746 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002747
Eric Laurent637e2d42018-11-15 12:24:31 -08002748 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002749 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302750 &out_devices,
2751 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002752 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002753 }
2754 }
2755
2756 if (out_snd_device == usecase->out_snd_device &&
2757 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302758
2759 if (!force_device_switch(usecase))
2760 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761 }
2762
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002763 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002764 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002765 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002766 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2767 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302768 }
2769
Aalique Grahame22e49102018-12-18 14:23:57 -08002770 if (out_snd_device != SND_DEVICE_NONE &&
2771 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2772 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2773 __func__,
2774 use_case_table[uc_id],
2775 adev->last_logged_snd_device[uc_id][0],
2776 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2777 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2778 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2779 -1,
2780 out_snd_device,
2781 platform_get_snd_device_name(out_snd_device),
2782 platform_get_snd_device_acdb_id(out_snd_device));
2783 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2784 }
2785 if (in_snd_device != SND_DEVICE_NONE &&
2786 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2787 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2788 __func__,
2789 use_case_table[uc_id],
2790 adev->last_logged_snd_device[uc_id][1],
2791 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2792 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2793 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2794 -1,
2795 in_snd_device,
2796 platform_get_snd_device_name(in_snd_device),
2797 platform_get_snd_device_acdb_id(in_snd_device));
2798 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2799 }
2800
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 /*
2803 * Limitation: While in call, to do a device switch we need to disable
2804 * and enable both RX and TX devices though one of them is same as current
2805 * device.
2806 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002807 if ((usecase->type == VOICE_CALL) &&
2808 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2809 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002810 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002811 }
2812
2813 if (((usecase->type == VOICE_CALL) ||
2814 (usecase->type == VOIP_CALL)) &&
2815 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2816 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302817 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002818 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002819 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002820
2821 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302822 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002823 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002824 }
2825
Aalique Grahame22e49102018-12-18 14:23:57 -08002826 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2827 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002828 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302829 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002830 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2831 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2832 else
2833 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302834 }
2835
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002836 /* Disable current sound devices */
2837 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002838 disable_audio_route(adev, usecase);
2839 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 }
2841
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002842 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002843 disable_audio_route(adev, usecase);
2844 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845 }
2846
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002847 /* Applicable only on the targets that has external modem.
2848 * New device information should be sent to modem before enabling
2849 * the devices to reduce in-call device switch time.
2850 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002851 if ((usecase->type == VOICE_CALL) &&
2852 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2853 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002854 status = platform_switch_voice_call_enable_device_config(adev->platform,
2855 out_snd_device,
2856 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002857 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002858
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002859 /* Enable new sound devices */
2860 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002861 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302862 if (platform_check_codec_asrc_support(adev->platform))
2863 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002864 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002865 }
2866
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002867 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302868 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002869 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002870 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002871
Avinash Vaish71a8b972014-07-24 15:36:33 +05302872 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002873 status = platform_switch_voice_call_device_post(adev->platform,
2874 out_snd_device,
2875 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302876 enable_audio_route_for_voice_usecases(adev, usecase);
2877 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002878
sangwoo170731f2013-06-08 15:36:36 +09002879 usecase->in_snd_device = in_snd_device;
2880 usecase->out_snd_device = out_snd_device;
2881
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302882 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2883 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302884 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002885 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002886 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002887 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2888 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2889 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2890 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2891 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2892 /*
2893 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2894 * configured device sample rate, if not update the COPP rate to be equal to the
2895 * device sample rate, else open COPP at stream sample rate
2896 */
2897 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2898 usecase->stream.out->sample_rate,
2899 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302900 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302901 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2902 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302903 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002904 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2905 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2906 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2907 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002908 }
2909 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002910
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002911 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002912
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002913 /* If input stream is already running then effect needs to be
2914 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002915 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002916 check_and_enable_effect(adev);
2917
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002918 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002919 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302920 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002921 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2922
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002923 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302924 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002925 voice_extn_compress_voip_is_started(adev))
2926 voice_set_sidetone(adev, out_snd_device, true);
2927 }
2928
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002929 /* Applicable only on the targets that has external modem.
2930 * Enable device command should be sent to modem only after
2931 * enabling voice call mixer controls
2932 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002933 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002934 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2935 out_snd_device,
2936 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302937
2938 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002939 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302940 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002941 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302942 if (is_bt_soc_on(adev) == false){
2943 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002944 if (in->pcm != NULL)
2945 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302946 }
2947 }
2948 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2949 && usecase->stream.out->started) {
2950 if (is_bt_soc_on(adev) == false) {
2951 ALOGD("BT SCO/A2DP disconnected while in connection");
2952 out_standby_l(&usecase->stream.out->stream.common);
2953 }
2954 }
2955 } else if ((usecase->stream.out != NULL) &&
2956 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302957 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2958 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08002959 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302960 usecase->stream.out->started) {
2961 if (is_bt_soc_on(adev) == false) {
2962 ALOGD("BT SCO/A2dp disconnected while in connection");
2963 out_standby_l(&usecase->stream.out->stream.common);
2964 }
2965 }
2966 }
2967
Yung Ti Su70cb8242018-06-22 17:38:47 +08002968 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002969 struct stream_out *voip_out = voip_usecase->stream.out;
2970 audio_extn_utils_send_app_type_gain(adev,
2971 voip_out->app_type_cfg.app_type,
2972 &voip_out->app_type_cfg.gain[0]);
2973 }
2974
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302975 ALOGD("%s: done",__func__);
2976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 return status;
2978}
2979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980static int stop_input_stream(struct stream_in *in)
2981{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302982 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302984
2985 if (in == NULL) {
2986 ALOGE("%s: stream_in ptr is NULL", __func__);
2987 return -EINVAL;
2988 }
2989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002991 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992
Eric Laurent994a6932013-07-17 11:51:42 -07002993 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002994 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 uc_info = get_usecase_from_list(adev, in->usecase);
2996 if (uc_info == NULL) {
2997 ALOGE("%s: Could not find the usecase (%d) in the list",
2998 __func__, in->usecase);
2999 return -EINVAL;
3000 }
3001
Carter Hsu2e429db2019-05-14 18:50:52 +08003002 priority_in = get_priority_input(adev);
3003
Derek Chenea197282019-01-07 17:35:01 -08003004 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3005 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003006
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003007 /* Close in-call recording streams */
3008 voice_check_and_stop_incall_rec_usecase(adev, in);
3009
Eric Laurent150dbfe2013-02-27 14:31:02 -08003010 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003011 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003012
3013 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003014 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003016 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303017 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3018
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003019 list_remove(&uc_info->list);
3020 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021
Carter Hsu2e429db2019-05-14 18:50:52 +08003022 if (priority_in == in) {
3023 priority_in = get_priority_input(adev);
3024 if (priority_in)
3025 select_devices(adev, priority_in->usecase);
3026 }
3027
Vatsal Buchac09ae062018-11-14 13:25:08 +05303028 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003029 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 return ret;
3031}
3032
3033int start_input_stream(struct stream_in *in)
3034{
3035 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003036 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303038
3039 if (in == NULL) {
3040 ALOGE("%s: stream_in ptr is NULL", __func__);
3041 return -EINVAL;
3042 }
3043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003045 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003046 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047
Mingming Yin2664a5b2015-09-03 10:53:11 -07003048 if (get_usecase_from_list(adev, usecase) == NULL)
3049 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303050 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3051 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003052
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303053 if (CARD_STATUS_OFFLINE == in->card_status||
3054 CARD_STATUS_OFFLINE == adev->card_status) {
3055 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303056 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303057 goto error_config;
3058 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303059
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003060 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303061 if (!adev->bt_sco_on) {
3062 ALOGE("%s: SCO profile is not ready, return error", __func__);
3063 ret = -EIO;
3064 goto error_config;
3065 }
3066 }
3067
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003068 /* Check if source matches incall recording usecase criteria */
3069 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3070 if (ret)
3071 goto error_config;
3072 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003073 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3074
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303075 if (audio_extn_cin_attached_usecase(in))
3076 audio_extn_cin_acquire_usecase(in);
3077
Mingming Yin2664a5b2015-09-03 10:53:11 -07003078 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3079 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3080 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003081 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003082 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003083
Eric Laurentb23d5282013-05-14 15:27:20 -07003084 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085 if (in->pcm_device_id < 0) {
3086 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3087 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003088 ret = -EINVAL;
3089 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003093
3094 if (!uc_info) {
3095 ret = -ENOMEM;
3096 goto error_config;
3097 }
3098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099 uc_info->id = in->usecase;
3100 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003101 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003102 list_init(&uc_info->device_list);
3103 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003104 uc_info->in_snd_device = SND_DEVICE_NONE;
3105 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003107 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003108 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303109 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3110 adev->perf_lock_opts,
3111 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003112 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113
Derek Chenea197282019-01-07 17:35:01 -08003114 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3115 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003116
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303117 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3118
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303119 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303120 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303121 if (ret)
3122 goto error_open;
3123 else
3124 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003125 }
3126
Haynes Mathew George16081042017-05-31 17:16:49 -07003127 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003128 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003129 ALOGE("%s: pcm stream not ready", __func__);
3130 goto error_open;
3131 }
3132 ret = pcm_start(in->pcm);
3133 if (ret < 0) {
3134 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3135 goto error_open;
3136 }
3137 } else {
3138 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3139 unsigned int pcm_open_retry_count = 0;
3140
3141 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
3142 flags |= PCM_MMAP | PCM_NOIRQ;
3143 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3144 } else if (in->realtime) {
3145 flags |= PCM_MMAP | PCM_NOIRQ;
3146 }
3147
Garmond Leunge2433c32017-09-28 21:51:22 -07003148 if (audio_extn_ffv_get_stream() == in) {
3149 ALOGD("%s: ffv stream, update pcm config", __func__);
3150 audio_extn_ffv_update_pcm_config(&config);
3151 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003152 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3153 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3154
3155 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003156 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003157 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003158 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003159 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303160 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303161 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3162 adev->card_status = CARD_STATUS_OFFLINE;
3163 in->card_status = CARD_STATUS_OFFLINE;
3164 ret = -EIO;
3165 goto error_open;
3166 }
3167
Haynes Mathew George16081042017-05-31 17:16:49 -07003168 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3169 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3170 if (in->pcm != NULL) {
3171 pcm_close(in->pcm);
3172 in->pcm = NULL;
3173 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003174 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003175 ret = -EIO;
3176 goto error_open;
3177 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003178 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003179 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3180 continue;
3181 }
3182 break;
3183 }
3184
3185 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003186 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003187 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003188 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003189 if (ret < 0) {
3190 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3191 pcm_close(in->pcm);
3192 in->pcm = NULL;
3193 goto error_open;
3194 }
3195 register_in_stream(in);
3196 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003197 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003198 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003199 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003200 if (ret < 0) {
3201 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003202 pcm_close(in->pcm);
3203 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003204 goto error_open;
3205 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003206 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003207 }
3208
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003209 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003210 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3211 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003212
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003213 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303214 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3215
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303216done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003217 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303218 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003219 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303220 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003221 return ret;
3222
3223error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003224 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303225 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003227
Eric Laurentc8400632013-02-14 19:04:54 -08003228error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303229 /*
3230 * sleep 50ms to allow sufficient time for kernel
3231 * drivers to recover incases like SSR.
3232 */
3233 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003234 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303235 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003236 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237}
3238
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003239void lock_input_stream(struct stream_in *in)
3240{
3241 pthread_mutex_lock(&in->pre_lock);
3242 pthread_mutex_lock(&in->lock);
3243 pthread_mutex_unlock(&in->pre_lock);
3244}
3245
3246void lock_output_stream(struct stream_out *out)
3247{
3248 pthread_mutex_lock(&out->pre_lock);
3249 pthread_mutex_lock(&out->lock);
3250 pthread_mutex_unlock(&out->pre_lock);
3251}
3252
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003253/* must be called with out->lock locked */
3254static int send_offload_cmd_l(struct stream_out* out, int command)
3255{
3256 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3257
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003258 if (!cmd) {
3259 ALOGE("failed to allocate mem for command 0x%x", command);
3260 return -ENOMEM;
3261 }
3262
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003263 ALOGVV("%s %d", __func__, command);
3264
3265 cmd->cmd = command;
3266 list_add_tail(&out->offload_cmd_list, &cmd->node);
3267 pthread_cond_signal(&out->offload_cond);
3268 return 0;
3269}
3270
3271/* must be called iwth out->lock locked */
3272static void stop_compressed_output_l(struct stream_out *out)
3273{
3274 out->offload_state = OFFLOAD_STATE_IDLE;
3275 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003276 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003277 if (out->compr != NULL) {
3278 compress_stop(out->compr);
3279 while (out->offload_thread_blocked) {
3280 pthread_cond_wait(&out->cond, &out->lock);
3281 }
3282 }
3283}
3284
Varun Balaraje49253e2017-07-06 19:48:56 +05303285bool is_interactive_usecase(audio_usecase_t uc_id)
3286{
3287 unsigned int i;
3288 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3289 if (uc_id == interactive_usecases[i])
3290 return true;
3291 }
3292 return false;
3293}
3294
3295static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3296{
3297 audio_usecase_t ret_uc = USECASE_INVALID;
3298 unsigned int intract_uc_index;
3299 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3300
3301 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3302 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3303 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3304 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3305 ret_uc = interactive_usecases[intract_uc_index];
3306 break;
3307 }
3308 }
3309
3310 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3311 return ret_uc;
3312}
3313
3314static void free_interactive_usecase(struct audio_device *adev,
3315 audio_usecase_t uc_id)
3316{
3317 unsigned int interact_uc_index;
3318 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3319
3320 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3321 if (interactive_usecases[interact_uc_index] == uc_id) {
3322 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3323 break;
3324 }
3325 }
3326 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3327}
3328
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003329bool is_offload_usecase(audio_usecase_t uc_id)
3330{
3331 unsigned int i;
3332 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3333 if (uc_id == offload_usecases[i])
3334 return true;
3335 }
3336 return false;
3337}
3338
Dhananjay Kumarac341582017-02-23 23:42:25 +05303339static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003340{
vivek mehta446c3962015-09-14 10:57:35 -07003341 audio_usecase_t ret_uc = USECASE_INVALID;
3342 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003343 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003344 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303345 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003346 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3347 else
3348 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003349
vivek mehta446c3962015-09-14 10:57:35 -07003350 pthread_mutex_lock(&adev->lock);
3351 if (get_usecase_from_list(adev, ret_uc) != NULL)
3352 ret_uc = USECASE_INVALID;
3353 pthread_mutex_unlock(&adev->lock);
3354
3355 return ret_uc;
3356 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003357
3358 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003359 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3360 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3361 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3362 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003363 break;
3364 }
3365 }
vivek mehta446c3962015-09-14 10:57:35 -07003366
3367 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3368 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003369}
3370
3371static void free_offload_usecase(struct audio_device *adev,
3372 audio_usecase_t uc_id)
3373{
vivek mehta446c3962015-09-14 10:57:35 -07003374 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003375 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003376
3377 if (!adev->multi_offload_enable)
3378 return;
3379
3380 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3381 if (offload_usecases[offload_uc_index] == uc_id) {
3382 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003383 break;
3384 }
3385 }
3386 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3387}
3388
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003389static void *offload_thread_loop(void *context)
3390{
3391 struct stream_out *out = (struct stream_out *) context;
3392 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003393 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003394
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003395 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003396 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003397 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3398
3399 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003400 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003401 out->offload_state = OFFLOAD_STATE_IDLE;
3402 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003403 for (;;) {
3404 struct offload_cmd *cmd = NULL;
3405 stream_callback_event_t event;
3406 bool send_callback = false;
3407
3408 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3409 __func__, list_empty(&out->offload_cmd_list),
3410 out->offload_state);
3411 if (list_empty(&out->offload_cmd_list)) {
3412 ALOGV("%s SLEEPING", __func__);
3413 pthread_cond_wait(&out->offload_cond, &out->lock);
3414 ALOGV("%s RUNNING", __func__);
3415 continue;
3416 }
3417
3418 item = list_head(&out->offload_cmd_list);
3419 cmd = node_to_item(item, struct offload_cmd, node);
3420 list_remove(item);
3421
3422 ALOGVV("%s STATE %d CMD %d out->compr %p",
3423 __func__, out->offload_state, cmd->cmd, out->compr);
3424
3425 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3426 free(cmd);
3427 break;
3428 }
3429
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003430 // allow OFFLOAD_CMD_ERROR reporting during standby
3431 // this is needed to handle failures during compress_open
3432 // Note however that on a pause timeout, the stream is closed
3433 // and no offload usecase will be active. Therefore this
3434 // special case is needed for compress_open failures alone
3435 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3436 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003437 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003438 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003439 pthread_cond_signal(&out->cond);
3440 continue;
3441 }
3442 out->offload_thread_blocked = true;
3443 pthread_mutex_unlock(&out->lock);
3444 send_callback = false;
3445 switch(cmd->cmd) {
3446 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003447 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003448 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003449 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003450 send_callback = true;
3451 event = STREAM_CBK_EVENT_WRITE_READY;
3452 break;
3453 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003454 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303455 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003456 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303457 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003458 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303459 if (ret < 0)
3460 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303461 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303462 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003463 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003464 else
3465 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003466 if (-ENETRESET != ret && !(-EINTR == ret &&
3467 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303468 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303469 pthread_mutex_lock(&out->lock);
3470 out->send_new_metadata = 1;
3471 out->send_next_track_params = true;
3472 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303473 event = STREAM_CBK_EVENT_DRAIN_READY;
3474 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3475 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303476 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003477 break;
3478 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003479 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003480 ret = compress_drain(out->compr);
3481 ALOGD("copl(%p):out of compress_drain", out);
3482 // EINTR check avoids drain interruption due to SSR
3483 if (-ENETRESET != ret && !(-EINTR == ret &&
3484 CARD_STATUS_OFFLINE == out->card_status)) {
3485 send_callback = true;
3486 event = STREAM_CBK_EVENT_DRAIN_READY;
3487 } else
3488 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003489 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303490 case OFFLOAD_CMD_ERROR:
3491 ALOGD("copl(%p): sending error callback to AF", out);
3492 send_callback = true;
3493 event = STREAM_CBK_EVENT_ERROR;
3494 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003495 default:
3496 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3497 break;
3498 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003499 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003500 out->offload_thread_blocked = false;
3501 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003502 if (send_callback && out->client_callback) {
3503 ALOGVV("%s: sending client_callback event %d", __func__, event);
3504 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003505 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003506 free(cmd);
3507 }
3508
3509 pthread_cond_signal(&out->cond);
3510 while (!list_empty(&out->offload_cmd_list)) {
3511 item = list_head(&out->offload_cmd_list);
3512 list_remove(item);
3513 free(node_to_item(item, struct offload_cmd, node));
3514 }
3515 pthread_mutex_unlock(&out->lock);
3516
3517 return NULL;
3518}
3519
3520static int create_offload_callback_thread(struct stream_out *out)
3521{
3522 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3523 list_init(&out->offload_cmd_list);
3524 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3525 offload_thread_loop, out);
3526 return 0;
3527}
3528
3529static int destroy_offload_callback_thread(struct stream_out *out)
3530{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003531 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003532 stop_compressed_output_l(out);
3533 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3534
3535 pthread_mutex_unlock(&out->lock);
3536 pthread_join(out->offload_thread, (void **) NULL);
3537 pthread_cond_destroy(&out->offload_cond);
3538
3539 return 0;
3540}
3541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542static int stop_output_stream(struct stream_out *out)
3543{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303544 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 struct audio_usecase *uc_info;
3546 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003547 bool has_voip_usecase =
3548 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549
Eric Laurent994a6932013-07-17 11:51:42 -07003550 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003551 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552 uc_info = get_usecase_from_list(adev, out->usecase);
3553 if (uc_info == NULL) {
3554 ALOGE("%s: Could not find the usecase (%d) in the list",
3555 __func__, out->usecase);
3556 return -EINVAL;
3557 }
3558
Derek Chenea197282019-01-07 17:35:01 -08003559 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3560 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003561
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003562 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303563 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003564 if (adev->visualizer_stop_output != NULL)
3565 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003566
3567 audio_extn_dts_remove_state_notifier_node(out->usecase);
3568
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003569 if (adev->offload_effects_stop_output != NULL)
3570 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003571 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3572 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3573 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003574 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003575
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003576 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3577 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003578 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003579 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003580
Eric Laurent150dbfe2013-02-27 14:31:02 -08003581 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003582 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003583
3584 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003585 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586
Aalique Grahame22e49102018-12-18 14:23:57 -08003587 audio_extn_extspk_update(adev->extspk);
3588
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003589 if (is_offload_usecase(out->usecase)) {
3590 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3591 adev->dsp_bit_width_enforce_mode,
3592 false);
3593 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003594 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003595 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3596 false);
3597
3598 if (ret != 0)
3599 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3600 /* default service interval was successfully updated,
3601 reopen USB backend with new service interval */
3602 ret = 0;
3603 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003604
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003605 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303606 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003607 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303608 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003609 ALOGV("Disable passthrough , reset mixer to pcm");
3610 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003611#ifdef AUDIO_GKI_ENABLED
3612 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3613 out->compr_config.codec->reserved[0] = 0;
3614#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003615 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003616#endif
Mingming Yin21854652016-04-13 11:54:02 -07003617 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003618 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3619 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003620
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303621 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003622 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303623 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303624
Manish Dewangan21a850a2017-08-14 12:03:55 +05303625 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003626 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3627 if (ret < 0)
3628 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3629 }
3630
juyuchen2d415992018-11-16 14:15:16 +08003631 /* 1) media + voip output routing to handset must route media back to
3632 speaker when voip stops.
3633 2) trigger voip input to reroute when voip output changes to
3634 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003635 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003636 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003637 struct listnode *node;
3638 struct audio_usecase *usecase;
3639 list_for_each(node, &adev->usecase_list) {
3640 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003641 if ((usecase->type == PCM_CAPTURE &&
3642 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3643 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003644 continue;
3645
3646 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3647 __func__, usecase->id, use_case_table[usecase->id],
3648 out->usecase, use_case_table[out->usecase]);
3649 select_devices(adev, usecase->id);
3650 }
3651 }
3652
Garmond Leung5fd0b552018-04-17 11:56:12 -07003653 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003654 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655 return ret;
3656}
3657
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003658struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3659 unsigned int flags, unsigned int pcm_open_retry_count,
3660 struct pcm_config *config)
3661{
3662 struct pcm* pcm = NULL;
3663
3664 while (1) {
3665 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3666 if (pcm == NULL || !pcm_is_ready(pcm)) {
3667 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3668 if (pcm != NULL) {
3669 pcm_close(pcm);
3670 pcm = NULL;
3671 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003672 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003673 return NULL;
3674
Weiyin Jiang72197252019-10-09 11:49:32 +08003675 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003676 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3677 continue;
3678 }
3679 break;
3680 }
3681
3682 if (pcm_is_ready(pcm)) {
3683 int ret = pcm_prepare(pcm);
3684 if (ret < 0) {
3685 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3686 pcm_close(pcm);
3687 pcm = NULL;
3688 }
3689 }
3690
3691 return pcm;
3692}
3693
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694int start_output_stream(struct stream_out *out)
3695{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003697 struct audio_usecase *uc_info;
3698 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003699 char mixer_ctl_name[128];
3700 struct mixer_ctl *ctl = NULL;
3701 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303702 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003703 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704
Haynes Mathew George380745d2017-10-04 15:27:45 -07003705 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003706 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3707 ret = -EINVAL;
3708 goto error_config;
3709 }
3710
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003711 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303712 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003713 get_device_types(&out->device_list), is_haptic_usecase);
3714
3715 bool is_speaker_active = compare_device_type(&out->device_list,
3716 AUDIO_DEVICE_OUT_SPEAKER);
3717 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3718 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303719
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303720 if (CARD_STATUS_OFFLINE == out->card_status ||
3721 CARD_STATUS_OFFLINE == adev->card_status) {
3722 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303723 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003724 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303725 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303726
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003727 //Update incall music usecase to reflect correct voice session
3728 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3729 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3730 if (ret != 0) {
3731 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3732 __func__, ret);
3733 goto error_config;
3734 }
3735 }
3736
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003737 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003738 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003739 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303740 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303741 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303742 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3743 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3744 ret = -EAGAIN;
3745 goto error_config;
3746 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303747 }
3748 }
3749 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003750 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303751 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003752 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303753 //combo usecase just by pass a2dp
3754 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003755 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303756 } else {
3757 ALOGE("%s: SCO profile is not ready, return error", __func__);
3758 ret = -EAGAIN;
3759 goto error_config;
3760 }
3761 }
3762 }
3763
Eric Laurentb23d5282013-05-14 15:27:20 -07003764 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 if (out->pcm_device_id < 0) {
3766 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3767 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003768 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003769 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 }
3771
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003772 if (is_haptic_usecase) {
3773 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3774 if (adev->haptic_pcm_device_id < 0) {
3775 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3776 __func__, adev->haptic_pcm_device_id, out->usecase);
3777 ret = -EINVAL;
3778 goto error_config;
3779 }
3780 }
3781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003783
3784 if (!uc_info) {
3785 ret = -ENOMEM;
3786 goto error_config;
3787 }
3788
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003789 uc_info->id = out->usecase;
3790 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003791 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003792 list_init(&uc_info->device_list);
3793 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003794 uc_info->in_snd_device = SND_DEVICE_NONE;
3795 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003796
3797 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003798 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003799 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3800 /* USB backend is not reopened immediately.
3801 This is eventually done as part of select_devices */
3802 }
3803
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003804 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805
Wei Wangf7ca6c92017-11-21 14:51:20 -08003806 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303807 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3808 adev->perf_lock_opts,
3809 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303810
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003811 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303812 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303813 if (audio_extn_passthru_is_enabled() &&
3814 audio_extn_passthru_is_passthrough_stream(out)) {
3815 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303816 }
3817 }
3818
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003819 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003820 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303821 if (!a2dp_combo) {
3822 check_a2dp_restore_l(adev, out, false);
3823 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003824 struct listnode dev;
3825 list_init(&dev);
3826 assign_devices(&dev, &out->device_list);
3827 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3828 reassign_device_list(&out->device_list,
3829 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003830 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003831 reassign_device_list(&out->device_list,
3832 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303833 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003834 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303835 }
3836 } else {
3837 select_devices(adev, out->usecase);
3838 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003839
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003840 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3841 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003842 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003843 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003844
Derek Chenea197282019-01-07 17:35:01 -08003845 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3846 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003847
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003848 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3849 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003850
3851 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003852 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003853 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3854 ALOGE("%s: pcm stream not ready", __func__);
3855 goto error_open;
3856 }
3857 ret = pcm_start(out->pcm);
3858 if (ret < 0) {
3859 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3860 goto error_open;
3861 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003862 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003863 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003864 unsigned int flags = PCM_OUT;
3865 unsigned int pcm_open_retry_count = 0;
3866 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3867 flags |= PCM_MMAP | PCM_NOIRQ;
3868 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003869 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003870 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003871 } else
3872 flags |= PCM_MONOTONIC;
3873
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003874 if ((adev->vr_audio_mode_enabled) &&
3875 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3876 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3877 "PCM_Dev %d Topology", out->pcm_device_id);
3878 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3879 if (!ctl) {
3880 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3881 __func__, mixer_ctl_name);
3882 } else {
3883 //if success use ULLPP
3884 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3885 __func__, mixer_ctl_name, out->pcm_device_id);
3886 //There is a still a possibility that some sessions
3887 // that request for FAST|RAW when 3D audio is active
3888 //can go through ULLPP. Ideally we expects apps to
3889 //listen to audio focus and stop concurrent playback
3890 //Also, we will look for mode flag (voice_in_communication)
3891 //before enabling the realtime flag.
3892 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3893 }
3894 }
3895
Surendar Karka91fa3682018-07-02 18:12:12 +05303896 if (out->realtime)
3897 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3898 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3899
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003900 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3901 flags, pcm_open_retry_count,
3902 &(out->config));
3903 if (out->pcm == NULL) {
3904 ret = -EIO;
3905 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003906 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003907
3908 if (is_haptic_usecase) {
3909 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3910 adev->haptic_pcm_device_id,
3911 flags, pcm_open_retry_count,
3912 &(adev->haptics_config));
3913 // failure to open haptics pcm shouldnt stop audio,
3914 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003915
3916 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3917 ALOGD("%s: enable haptic audio synchronization", __func__);
3918 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3919 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003920 }
3921
Surendar Karka91fa3682018-07-02 18:12:12 +05303922 if (!out->realtime)
3923 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303924 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003925
Zhou Song2b8f28f2017-09-11 10:51:38 +08003926 // apply volume for voip playback after path is set up
3927 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3928 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303929 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3930 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303931 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3932 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003933 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3934 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303935 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003936 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08003937 /*
3938 * set custom channel map if:
3939 * 1. neither mono nor stereo clips i.e. channels > 2 OR
3940 * 2. custom channel map has been set by client
3941 * else default channel map of FC/FR/FL can always be set to DSP
3942 */
3943 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
3944 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3945 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003946 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3947 adev->dsp_bit_width_enforce_mode,
3948 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003950 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003951 out->compr = compress_open(adev->snd_card,
3952 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003953 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003954 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303955 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303956 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3957 adev->card_status = CARD_STATUS_OFFLINE;
3958 out->card_status = CARD_STATUS_OFFLINE;
3959 ret = -EIO;
3960 goto error_open;
3961 }
3962
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003963 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003964 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003965 compress_close(out->compr);
3966 out->compr = NULL;
3967 ret = -EIO;
3968 goto error_open;
3969 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303970 /* compress_open sends params of the track, so reset the flag here */
3971 out->is_compr_metadata_avail = false;
3972
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003973 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003974 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003975
Fred Oh3f43e742015-03-04 18:42:34 -08003976 /* Since small bufs uses blocking writes, a write will be blocked
3977 for the default max poll time (20s) in the event of an SSR.
3978 Reduce the poll time to observe and deal with SSR faster.
3979 */
Ashish Jain5106d362016-05-11 19:23:33 +05303980 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003981 compress_set_max_poll_wait(out->compr, 1000);
3982 }
3983
Manish Dewangan69426c82017-01-30 17:35:36 +05303984 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303985 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303986
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003987 audio_extn_dts_create_state_notifier_node(out->usecase);
3988 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3989 popcount(out->channel_mask),
3990 out->playback_started);
3991
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003992#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303993 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003994 audio_extn_dolby_send_ddp_endp_params(adev);
3995#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303996 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3997 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003998 if (adev->visualizer_start_output != NULL)
3999 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4000 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304001 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004002 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004003 }
Derek Chenf13dd492018-11-13 14:53:51 -08004004
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004005 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004006 /* Update cached volume from media to offload/direct stream */
4007 struct listnode *node = NULL;
4008 list_for_each(node, &adev->active_outputs_list) {
4009 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4010 streams_output_ctxt_t,
4011 list);
4012 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4013 out->volume_l = out_ctxt->output->volume_l;
4014 out->volume_r = out_ctxt->output->volume_r;
4015 }
4016 }
4017 out_set_compr_volume(&out->stream,
4018 out->volume_l, out->volume_r);
4019 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004020 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004021
4022 if (ret == 0) {
4023 register_out_stream(out);
4024 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004025 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4026 ALOGE("%s: pcm stream not ready", __func__);
4027 goto error_open;
4028 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004029 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004030 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004031 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004032 if (ret < 0)
4033 goto error_open;
4034 }
4035 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004036 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304037 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004038 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004039
vivek mehtad15d2bf2019-05-17 13:35:10 -07004040 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4041 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4042 audio_low_latency_hint_start();
4043 }
4044
Manish Dewangan21a850a2017-08-14 12:03:55 +05304045 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004046 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004047 if (ret < 0)
4048 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4049 }
4050
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004051 // consider a scenario where on pause lower layers are tear down.
4052 // so on resume, swap mixer control need to be sent only when
4053 // backend is active, hence rather than sending from enable device
4054 // sending it from start of streamtream
4055
4056 platform_set_swap_channels(adev, true);
4057
Haynes Mathew George380745d2017-10-04 15:27:45 -07004058 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304059 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004060 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004061error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004062 if (adev->haptic_pcm) {
4063 pcm_close(adev->haptic_pcm);
4064 adev->haptic_pcm = NULL;
4065 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004066 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304067 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004069error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304070 /*
4071 * sleep 50ms to allow sufficient time for kernel
4072 * drivers to recover incases like SSR.
4073 */
4074 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004075error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004076 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304077 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004078 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004079}
4080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004081static int check_input_parameters(uint32_t sample_rate,
4082 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004083 int channel_count,
4084 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004086 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304088 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4089 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4090 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004091 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004092 !audio_extn_compr_cap_format_supported(format) &&
4093 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004094 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004095
Aalique Grahame22e49102018-12-18 14:23:57 -08004096 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4097 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4098 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4099 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4100 return -EINVAL;
4101 }
4102
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004103 switch (channel_count) {
4104 case 1:
4105 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304106 case 3:
4107 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004108 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004109 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304110 case 10:
4111 case 12:
4112 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004113 break;
4114 default:
4115 ret = -EINVAL;
4116 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004117
4118 switch (sample_rate) {
4119 case 8000:
4120 case 11025:
4121 case 12000:
4122 case 16000:
4123 case 22050:
4124 case 24000:
4125 case 32000:
4126 case 44100:
4127 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004128 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304129 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004130 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304131 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132 break;
4133 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004134 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135 }
4136
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004137 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138}
4139
Naresh Tanniru04f71882018-06-26 17:46:22 +05304140
4141/** Add a value in a list if not already present.
4142 * @return true if value was successfully inserted or already present,
4143 * false if the list is full and does not contain the value.
4144 */
4145static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4146 for (size_t i = 0; i < list_length; i++) {
4147 if (list[i] == value) return true; // value is already present
4148 if (list[i] == 0) { // no values in this slot
4149 list[i] = value;
4150 return true; // value inserted
4151 }
4152 }
4153 return false; // could not insert value
4154}
4155
4156/** Add channel_mask in supported_channel_masks if not already present.
4157 * @return true if channel_mask was successfully inserted or already present,
4158 * false if supported_channel_masks is full and does not contain channel_mask.
4159 */
4160static void register_channel_mask(audio_channel_mask_t channel_mask,
4161 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4162 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4163 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4164}
4165
4166/** Add format in supported_formats if not already present.
4167 * @return true if format was successfully inserted or already present,
4168 * false if supported_formats is full and does not contain format.
4169 */
4170static void register_format(audio_format_t format,
4171 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4172 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4173 "%s: stream can not declare supporting its format %x", __func__, format);
4174}
4175/** Add sample_rate in supported_sample_rates if not already present.
4176 * @return true if sample_rate was successfully inserted or already present,
4177 * false if supported_sample_rates is full and does not contain sample_rate.
4178 */
4179static void register_sample_rate(uint32_t sample_rate,
4180 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4181 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4182 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4183}
4184
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004185static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4186{
4187 uint32_t high = num1, low = num2, temp = 0;
4188
4189 if (!num1 || !num2)
4190 return 0;
4191
4192 if (num1 < num2) {
4193 high = num2;
4194 low = num1;
4195 }
4196
4197 while (low != 0) {
4198 temp = low;
4199 low = high % low;
4200 high = temp;
4201 }
4202 return (num1 * num2)/high;
4203}
4204
4205static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4206{
4207 uint32_t remainder = 0;
4208
4209 if (!multiplier)
4210 return num;
4211
4212 remainder = num % multiplier;
4213 if (remainder)
4214 num += (multiplier - remainder);
4215
4216 return num;
4217}
4218
Aalique Grahame22e49102018-12-18 14:23:57 -08004219static size_t get_stream_buffer_size(size_t duration_ms,
4220 uint32_t sample_rate,
4221 audio_format_t format,
4222 int channel_count,
4223 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004224{
4225 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004226 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004227
Aalique Grahame22e49102018-12-18 14:23:57 -08004228 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004229 if (is_low_latency)
4230 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304231
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004232 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004233 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004234
Ralf Herzbd08d632018-09-28 15:50:49 +02004235 /* make sure the size is multiple of 32 bytes and additionally multiple of
4236 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004237 * At 48 kHz mono 16-bit PCM:
4238 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4239 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004240 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004241 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004242 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004243
4244 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245}
4246
Aalique Grahame22e49102018-12-18 14:23:57 -08004247static size_t get_input_buffer_size(uint32_t sample_rate,
4248 audio_format_t format,
4249 int channel_count,
4250 bool is_low_latency)
4251{
4252 /* Don't know if USB HIFI in this context so use true to be conservative */
4253 if (check_input_parameters(sample_rate, format, channel_count,
4254 true /*is_usb_hifi */) != 0)
4255 return 0;
4256
4257 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4258 sample_rate,
4259 format,
4260 channel_count,
4261 is_low_latency);
4262}
4263
Derek Chenf6318be2017-06-12 17:16:24 -04004264size_t get_output_period_size(uint32_t sample_rate,
4265 audio_format_t format,
4266 int channel_count,
4267 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304268{
4269 size_t size = 0;
4270 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4271
4272 if ((duration == 0) || (sample_rate == 0) ||
4273 (bytes_per_sample == 0) || (channel_count == 0)) {
4274 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4275 bytes_per_sample, channel_count);
4276 return -EINVAL;
4277 }
4278
4279 size = (sample_rate *
4280 duration *
4281 bytes_per_sample *
4282 channel_count) / 1000;
4283 /*
4284 * To have same PCM samples for all channels, the buffer size requires to
4285 * be multiple of (number of channels * bytes per sample)
4286 * For writes to succeed, the buffer must be written at address which is multiple of 32
4287 */
4288 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4289
4290 return (size/(channel_count * bytes_per_sample));
4291}
4292
Zhou Song48453a02018-01-10 17:50:59 +08004293static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304294{
4295 uint64_t actual_frames_rendered = 0;
4296 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4297
4298 /* This adjustment accounts for buffering after app processor.
4299 * It is based on estimated DSP latency per use case, rather than exact.
4300 */
4301 int64_t platform_latency = platform_render_latency(out->usecase) *
4302 out->sample_rate / 1000000LL;
4303
Zhou Song48453a02018-01-10 17:50:59 +08004304 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304305 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4306 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4307 * hence only estimate.
4308 */
George Gao62ebc722019-07-29 16:29:44 -07004309 uint64_t signed_frames = 0;
4310 if (out->written >= kernel_buffer_size)
4311 signed_frames = out->written - kernel_buffer_size;
Ashish Jain5106d362016-05-11 19:23:33 +05304312
George Gao62ebc722019-07-29 16:29:44 -07004313 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask));
4314 if (signed_frames >= platform_latency)
4315 signed_frames = signed_frames - platform_latency;
Ashish Jain5106d362016-05-11 19:23:33 +05304316
Zhou Song48453a02018-01-10 17:50:59 +08004317 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304318 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004319 if (timestamp != NULL )
4320 *timestamp = out->writeAt;
4321 } else if (timestamp != NULL) {
4322 clock_gettime(CLOCK_MONOTONIC, timestamp);
4323 }
4324 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304325
4326 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
George Gao62ebc722019-07-29 16:29:44 -07004327 "bytes/sample %zu channel count %d", __func__, signed_frames,
Ashish Jain5106d362016-05-11 19:23:33 +05304328 (long long int)out->written, (int)kernel_buffer_size,
4329 audio_bytes_per_sample(out->compr_config.codec->format),
4330 popcount(out->channel_mask));
4331
4332 return actual_frames_rendered;
4333}
4334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4336{
4337 struct stream_out *out = (struct stream_out *)stream;
4338
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004339 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004340}
4341
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004342static int out_set_sample_rate(struct audio_stream *stream __unused,
4343 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344{
4345 return -ENOSYS;
4346}
4347
4348static size_t out_get_buffer_size(const struct audio_stream *stream)
4349{
4350 struct stream_out *out = (struct stream_out *)stream;
4351
Varun Balaraje49253e2017-07-06 19:48:56 +05304352 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304353 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304354 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304355 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4356 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4357 else
4358 return out->compr_config.fragment_size;
4359 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004360 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304361 else if (is_offload_usecase(out->usecase) &&
4362 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304363 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004364
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004365 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004366 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004367}
4368
4369static uint32_t out_get_channels(const struct audio_stream *stream)
4370{
4371 struct stream_out *out = (struct stream_out *)stream;
4372
4373 return out->channel_mask;
4374}
4375
4376static audio_format_t out_get_format(const struct audio_stream *stream)
4377{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004378 struct stream_out *out = (struct stream_out *)stream;
4379
4380 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381}
4382
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004383static int out_set_format(struct audio_stream *stream __unused,
4384 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004385{
4386 return -ENOSYS;
4387}
4388
4389static int out_standby(struct audio_stream *stream)
4390{
4391 struct stream_out *out = (struct stream_out *)stream;
4392 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004393 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004394
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304395 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4396 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004397
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004398 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004399 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004400 if (adev->adm_deregister_stream)
4401 adev->adm_deregister_stream(adev->adm_data, out->handle);
4402
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004403 if (is_offload_usecase(out->usecase))
4404 stop_compressed_output_l(out);
4405
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004406 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004407 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004408 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4409 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304410 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004411 pthread_mutex_unlock(&adev->lock);
4412 pthread_mutex_unlock(&out->lock);
4413 ALOGD("VOIP output entered standby");
4414 return 0;
4415 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004416 if (out->pcm) {
4417 pcm_close(out->pcm);
4418 out->pcm = NULL;
4419 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004420 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4421 do_stop = out->playback_started;
4422 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004423
4424 if (out->mmap_shared_memory_fd >= 0) {
4425 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4426 __func__, out->mmap_shared_memory_fd);
4427 close(out->mmap_shared_memory_fd);
4428 out->mmap_shared_memory_fd = -1;
4429 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004430 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004431 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004432 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304433 out->send_next_track_params = false;
4434 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004435 out->gapless_mdata.encoder_delay = 0;
4436 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004437 if (out->compr != NULL) {
4438 compress_close(out->compr);
4439 out->compr = NULL;
4440 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004441 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004442 if (do_stop) {
4443 stop_output_stream(out);
4444 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304445 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004446 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004447 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004448 }
4449 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304450 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004451 return 0;
4452}
4453
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304454static int out_on_error(struct audio_stream *stream)
4455{
4456 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004457 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304458
4459 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004460 // always send CMD_ERROR for offload streams, this
4461 // is needed e.g. when SSR happens within compress_open
4462 // since the stream is active, offload_callback_thread is also active.
4463 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4464 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004465 }
4466 pthread_mutex_unlock(&out->lock);
4467
4468 status = out_standby(&out->stream.common);
4469
4470 lock_output_stream(out);
4471 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004472 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304473 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304474
4475 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4476 ALOGD("Setting previous card status if offline");
4477 out->prev_card_status_offline = true;
4478 }
4479
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304480 pthread_mutex_unlock(&out->lock);
4481
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004482 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304483}
4484
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304485/*
4486 *standby implementation without locks, assumes that the callee already
4487 *has taken adev and out lock.
4488 */
4489int out_standby_l(struct audio_stream *stream)
4490{
4491 struct stream_out *out = (struct stream_out *)stream;
4492 struct audio_device *adev = out->dev;
4493
4494 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4495 stream, out->usecase, use_case_table[out->usecase]);
4496
4497 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004498 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304499 if (adev->adm_deregister_stream)
4500 adev->adm_deregister_stream(adev->adm_data, out->handle);
4501
4502 if (is_offload_usecase(out->usecase))
4503 stop_compressed_output_l(out);
4504
4505 out->standby = true;
4506 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4507 voice_extn_compress_voip_close_output_stream(stream);
4508 out->started = 0;
4509 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004510 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304511 return 0;
4512 } else if (!is_offload_usecase(out->usecase)) {
4513 if (out->pcm) {
4514 pcm_close(out->pcm);
4515 out->pcm = NULL;
4516 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004517 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4518 if (adev->haptic_pcm) {
4519 pcm_close(adev->haptic_pcm);
4520 adev->haptic_pcm = NULL;
4521 }
4522
4523 if (adev->haptic_buffer != NULL) {
4524 free(adev->haptic_buffer);
4525 adev->haptic_buffer = NULL;
4526 adev->haptic_buffer_size = 0;
4527 }
4528 adev->haptic_pcm_device_id = 0;
4529 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304530 } else {
4531 ALOGD("copl(%p):standby", out);
4532 out->send_next_track_params = false;
4533 out->is_compr_metadata_avail = false;
4534 out->gapless_mdata.encoder_delay = 0;
4535 out->gapless_mdata.encoder_padding = 0;
4536 if (out->compr != NULL) {
4537 compress_close(out->compr);
4538 out->compr = NULL;
4539 }
4540 }
4541 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004542 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304543 }
4544 ALOGD("%s: exit", __func__);
4545 return 0;
4546}
4547
Aalique Grahame22e49102018-12-18 14:23:57 -08004548static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004549{
Aalique Grahame22e49102018-12-18 14:23:57 -08004550 struct stream_out *out = (struct stream_out *)stream;
4551
4552 // We try to get the lock for consistency,
4553 // but it isn't necessary for these variables.
4554 // If we're not in standby, we may be blocked on a write.
4555 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4556 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4557 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4558
Andy Hunga1f48fa2019-07-01 18:14:53 -07004559 char buffer[256]; // for statistics formatting
4560 if (!is_offload_usecase(out->usecase)) {
4561 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4562 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4563 }
4564
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004565 if (out->start_latency_ms.n > 0) {
4566 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4567 dprintf(fd, " Start latency ms: %s\n", buffer);
4568 }
4569
Aalique Grahame22e49102018-12-18 14:23:57 -08004570 if (locked) {
4571 pthread_mutex_unlock(&out->lock);
4572 }
4573
4574 // dump error info
4575 (void)error_log_dump(
4576 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4577
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578 return 0;
4579}
4580
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004581static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4582{
4583 int ret = 0;
4584 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004585
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004586 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004587 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004588 return -EINVAL;
4589 }
4590
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304591 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004592
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004593 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4594 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304595 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004596 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004597 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4598 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304599 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004600 }
4601
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004602 ALOGV("%s new encoder delay %u and padding %u", __func__,
4603 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4604
4605 return 0;
4606}
4607
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004608static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4609{
4610 return out == adev->primary_output || out == adev->voice_tx_output;
4611}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004612
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304613// note: this call is safe only if the stream_cb is
4614// removed first in close_output_stream (as is done now).
4615static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4616{
4617 if (!stream || !parms)
4618 return;
4619
4620 struct stream_out *out = (struct stream_out *)stream;
4621 struct audio_device *adev = out->dev;
4622
4623 card_status_t status;
4624 int card;
4625 if (parse_snd_card_status(parms, &card, &status) < 0)
4626 return;
4627
4628 pthread_mutex_lock(&adev->lock);
4629 bool valid_cb = (card == adev->snd_card);
4630 pthread_mutex_unlock(&adev->lock);
4631
4632 if (!valid_cb)
4633 return;
4634
4635 lock_output_stream(out);
4636 if (out->card_status != status)
4637 out->card_status = status;
4638 pthread_mutex_unlock(&out->lock);
4639
4640 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4641 use_case_table[out->usecase],
4642 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4643
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304644 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304645 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304646 if (voice_is_call_state_active(adev) &&
4647 out == adev->primary_output) {
4648 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4649 pthread_mutex_lock(&adev->lock);
4650 voice_stop_call(adev);
4651 adev->mode = AUDIO_MODE_NORMAL;
4652 pthread_mutex_unlock(&adev->lock);
4653 }
4654 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304655 return;
4656}
4657
Kevin Rocardfce19002017-08-07 19:21:36 -07004658static int get_alive_usb_card(struct str_parms* parms) {
4659 int card;
4660 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4661 !audio_extn_usb_alive(card)) {
4662 return card;
4663 }
4664 return -ENODEV;
4665}
4666
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004667int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004668 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004669{
4670 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004671 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004672 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004673 bool bypass_a2dp = false;
4674 bool reconfig = false;
4675 unsigned long service_interval = 0;
4676
4677 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004678 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4679
4680 list_init(&new_devices);
4681 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004682
4683 lock_output_stream(out);
4684 pthread_mutex_lock(&adev->lock);
4685
4686 /*
4687 * When HDMI cable is unplugged the music playback is paused and
4688 * the policy manager sends routing=0. But the audioflinger continues
4689 * to write data until standby time (3sec). As the HDMI core is
4690 * turned off, the write gets blocked.
4691 * Avoid this by routing audio to speaker until standby.
4692 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004693 if (is_single_device_type_equal(&out->device_list,
4694 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004695 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004696 !audio_extn_passthru_is_passthrough_stream(out) &&
4697 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004698 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004699 }
4700 /*
4701 * When A2DP is disconnected the
4702 * music playback is paused and the policy manager sends routing=0
4703 * But the audioflinger continues to write data until standby time
4704 * (3sec). As BT is turned off, the write gets blocked.
4705 * Avoid this by routing audio to speaker until standby.
4706 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004707 if (is_a2dp_out_device_type(&out->device_list) &&
4708 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004709 !audio_extn_a2dp_source_is_ready() &&
4710 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004711 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004712 }
4713 /*
4714 * When USB headset is disconnected the music platback paused
4715 * and the policy manager send routing=0. But if the USB is connected
4716 * back before the standby time, AFE is not closed and opened
4717 * when USB is connected back. So routing to speker will guarantee
4718 * AFE reconfiguration and AFE will be opend once USB is connected again
4719 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004720 if (is_usb_out_device_type(&out->device_list) &&
4721 list_empty(&new_devices) &&
4722 !audio_extn_usb_connected(NULL)) {
4723 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4724 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004725 /* To avoid a2dp to sco overlapping / BT device improper state
4726 * check with BT lib about a2dp streaming support before routing
4727 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004728 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004729 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004730 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4731 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004732 //combo usecase just by pass a2dp
4733 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4734 bypass_a2dp = true;
4735 } else {
4736 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4737 /* update device to a2dp and don't route as BT returned error
4738 * However it is still possible a2dp routing called because
4739 * of current active device disconnection (like wired headset)
4740 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004741 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004742 pthread_mutex_unlock(&adev->lock);
4743 pthread_mutex_unlock(&out->lock);
4744 goto error;
4745 }
4746 }
4747 }
4748
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004749 // Workaround: If routing to an non existing usb device, fail gracefully
4750 // The routing request will otherwise block during 10 second
4751 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004752 if (is_usb_out_device_type(&new_devices)) {
4753 struct str_parms *parms =
4754 str_parms_create_str(get_usb_device_address(&new_devices));
4755 if (!parms)
4756 goto error;
4757 if ((card = get_alive_usb_card(parms)) >= 0) {
4758 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4759 pthread_mutex_unlock(&adev->lock);
4760 pthread_mutex_unlock(&out->lock);
4761 str_parms_destroy(parms);
4762 ret = -ENOSYS;
4763 goto error;
4764 }
4765 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004766 }
4767
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004768 // Workaround: If routing to an non existing hdmi device, fail gracefully
4769 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4770 (platform_get_edid_info_v2(adev->platform,
4771 out->extconn.cs.controller,
4772 out->extconn.cs.stream) != 0)) {
4773 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4774 pthread_mutex_unlock(&adev->lock);
4775 pthread_mutex_unlock(&out->lock);
4776 ret = -ENOSYS;
4777 goto error;
4778 }
4779
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004780 /*
4781 * select_devices() call below switches all the usecases on the same
4782 * backend to the new device. Refer to check_usecases_codec_backend() in
4783 * the select_devices(). But how do we undo this?
4784 *
4785 * For example, music playback is active on headset (deep-buffer usecase)
4786 * and if we go to ringtones and select a ringtone, low-latency usecase
4787 * will be started on headset+speaker. As we can't enable headset+speaker
4788 * and headset devices at the same time, select_devices() switches the music
4789 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4790 * So when the ringtone playback is completed, how do we undo the same?
4791 *
4792 * We are relying on the out_set_parameters() call on deep-buffer output,
4793 * once the ringtone playback is ended.
4794 * NOTE: We should not check if the current devices are same as new devices.
4795 * Because select_devices() must be called to switch back the music
4796 * playback to headset.
4797 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004798 if (!list_empty(&new_devices)) {
4799 bool same_dev = compare_devices(&out->device_list, &new_devices);
4800 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004801
4802 if (output_drives_call(adev, out)) {
4803 if (!voice_is_call_state_active(adev)) {
4804 if (adev->mode == AUDIO_MODE_IN_CALL) {
4805 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004806 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004807 service_interval =
4808 audio_extn_usb_find_service_interval(true, true /*playback*/);
4809 audio_extn_usb_set_service_interval(true /*playback*/,
4810 service_interval,
4811 &reconfig);
4812 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4813 }
4814 ret = voice_start_call(adev);
4815 }
4816 } else {
4817 adev->current_call_output = out;
4818 voice_update_devices_for_all_voice_usecases(adev);
4819 }
4820 }
4821
4822 if (!out->standby) {
4823 if (!same_dev) {
4824 ALOGV("update routing change");
4825 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4826 adev->perf_lock_opts,
4827 adev->perf_lock_opts_size);
4828 if (adev->adm_on_routing_change)
4829 adev->adm_on_routing_change(adev->adm_data,
4830 out->handle);
4831 }
4832 if (!bypass_a2dp) {
4833 select_devices(adev, out->usecase);
4834 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004835 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4836 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004837 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004838 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004839 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004840 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004841 }
4842
4843 if (!same_dev) {
4844 // on device switch force swap, lower functions will make sure
4845 // to check if swap is allowed or not.
4846 platform_set_swap_channels(adev, true);
4847 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4848 }
4849 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4850 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004851 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004852 pthread_mutex_lock(&out->compr_mute_lock);
4853 out->a2dp_compress_mute = false;
4854 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4855 pthread_mutex_unlock(&out->compr_mute_lock);
4856 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4857 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4858 }
4859 }
4860 }
4861
4862 pthread_mutex_unlock(&adev->lock);
4863 pthread_mutex_unlock(&out->lock);
4864
4865 /*handles device and call state changes*/
4866 audio_extn_extspk_update(adev->extspk);
4867
4868error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004869 ALOGV("%s: exit: code(%d)", __func__, ret);
4870 return ret;
4871}
4872
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004873static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4874{
4875 struct stream_out *out = (struct stream_out *)stream;
4876 struct audio_device *adev = out->dev;
4877 struct str_parms *parms;
4878 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004879 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004880 int ext_controller = -1;
4881 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004882
sangwoobc677242013-08-08 16:53:43 +09004883 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004884 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304886 if (!parms)
4887 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004888
4889 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4890 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08004891 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004892 out->extconn.cs.controller = ext_controller;
4893 out->extconn.cs.stream = ext_stream;
4894 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4895 use_case_table[out->usecase], out->extconn.cs.controller,
4896 out->extconn.cs.stream);
4897 }
4898
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004899 if (out == adev->primary_output) {
4900 pthread_mutex_lock(&adev->lock);
4901 audio_extn_set_parameters(adev, parms);
4902 pthread_mutex_unlock(&adev->lock);
4903 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004904 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004905 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004906 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004907
4908 audio_extn_dts_create_state_notifier_node(out->usecase);
4909 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4910 popcount(out->channel_mask),
4911 out->playback_started);
4912
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004913 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004914 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004915
Surendar Karkaf51b5842018-04-26 11:28:38 +05304916 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4917 sizeof(value));
4918 if (err >= 0) {
4919 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4920 audio_extn_send_dual_mono_mixing_coefficients(out);
4921 }
4922
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304923 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4924 if (err >= 0) {
4925 strlcpy(out->profile, value, sizeof(out->profile));
4926 ALOGV("updating stream profile with value '%s'", out->profile);
4927 lock_output_stream(out);
4928 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4929 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004930 &out->device_list, out->flags,
4931 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304932 out->sample_rate, out->bit_width,
4933 out->channel_mask, out->profile,
4934 &out->app_type_cfg);
4935 pthread_mutex_unlock(&out->lock);
4936 }
4937
Alexy Joseph98988832017-01-13 14:56:59 -08004938 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004939 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4940 // and vendor.audio.hal.output.suspend.supported is set to true
4941 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004942 //check suspend parameter only for low latency and if the property
4943 //is enabled
4944 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4945 ALOGI("%s: got suspend_playback %s", __func__, value);
4946 lock_output_stream(out);
4947 if (!strncmp(value, "false", 5)) {
4948 //suspend_playback=false is supposed to set QOS value back to 75%
4949 //the mixer control sent with value Enable will achieve that
4950 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4951 } else if (!strncmp (value, "true", 4)) {
4952 //suspend_playback=true is supposed to remove QOS value
4953 //resetting the mixer control will set the default value
4954 //for the mixer control which is Disable and this removes the QOS vote
4955 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4956 } else {
4957 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4958 " got %s", __func__, value);
4959 ret = -1;
4960 }
4961
4962 if (ret != 0) {
4963 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4964 __func__, out->pm_qos_mixer_path, ret);
4965 }
4966
4967 pthread_mutex_unlock(&out->lock);
4968 }
4969 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004970
Alexy Joseph98988832017-01-13 14:56:59 -08004971 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004972 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304973error:
Eric Laurent994a6932013-07-17 11:51:42 -07004974 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004975 return ret;
4976}
4977
Paul McLeana50b7332018-12-17 08:24:21 -07004978static int in_set_microphone_direction(const struct audio_stream_in *stream,
4979 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004980 struct stream_in *in = (struct stream_in *)stream;
4981
4982 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4983
4984 in->direction = dir;
4985
4986 if (in->standby)
4987 return 0;
4988
4989 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004990}
4991
4992static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004993 struct stream_in *in = (struct stream_in *)stream;
4994
4995 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4996
4997 if (zoom > 1.0 || zoom < -1.0)
4998 return -EINVAL;
4999
5000 in->zoom = zoom;
5001
5002 if (in->standby)
5003 return 0;
5004
5005 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005006}
5007
5008
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005009static bool stream_get_parameter_channels(struct str_parms *query,
5010 struct str_parms *reply,
5011 audio_channel_mask_t *supported_channel_masks) {
5012 int ret = -1;
5013 char value[512];
5014 bool first = true;
5015 size_t i, j;
5016
5017 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5018 ret = 0;
5019 value[0] = '\0';
5020 i = 0;
5021 while (supported_channel_masks[i] != 0) {
5022 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5023 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5024 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305025 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005026
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305027 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005028 first = false;
5029 break;
5030 }
5031 }
5032 i++;
5033 }
5034 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5035 }
5036 return ret == 0;
5037}
5038
5039static bool stream_get_parameter_formats(struct str_parms *query,
5040 struct str_parms *reply,
5041 audio_format_t *supported_formats) {
5042 int ret = -1;
5043 char value[256];
5044 size_t i, j;
5045 bool first = true;
5046
5047 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5048 ret = 0;
5049 value[0] = '\0';
5050 i = 0;
5051 while (supported_formats[i] != 0) {
5052 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5053 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5054 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305055 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005056 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305057 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005058 first = false;
5059 break;
5060 }
5061 }
5062 i++;
5063 }
5064 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5065 }
5066 return ret == 0;
5067}
5068
5069static bool stream_get_parameter_rates(struct str_parms *query,
5070 struct str_parms *reply,
5071 uint32_t *supported_sample_rates) {
5072
5073 int i;
5074 char value[256];
5075 int ret = -1;
5076 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5077 ret = 0;
5078 value[0] = '\0';
5079 i=0;
5080 int cursor = 0;
5081 while (supported_sample_rates[i]) {
5082 int avail = sizeof(value) - cursor;
5083 ret = snprintf(value + cursor, avail, "%s%d",
5084 cursor > 0 ? "|" : "",
5085 supported_sample_rates[i]);
5086 if (ret < 0 || ret >= avail) {
5087 // if cursor is at the last element of the array
5088 // overwrite with \0 is duplicate work as
5089 // snprintf already put a \0 in place.
5090 // else
5091 // we had space to write the '|' at value[cursor]
5092 // (which will be overwritten) or no space to fill
5093 // the first element (=> cursor == 0)
5094 value[cursor] = '\0';
5095 break;
5096 }
5097 cursor += ret;
5098 ++i;
5099 }
5100 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5101 value);
5102 }
5103 return ret >= 0;
5104}
5105
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005106static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5107{
5108 struct stream_out *out = (struct stream_out *)stream;
5109 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005110 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005111 char value[256];
5112 struct str_parms *reply = str_parms_create();
5113 size_t i, j;
5114 int ret;
5115 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005116
5117 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005118 if (reply) {
5119 str_parms_destroy(reply);
5120 }
5121 if (query) {
5122 str_parms_destroy(query);
5123 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005124 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5125 return NULL;
5126 }
5127
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005128 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005129 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5130 if (ret >= 0) {
5131 value[0] = '\0';
5132 i = 0;
5133 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005134 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5135 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005136 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005137 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005138 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005139 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005140 first = false;
5141 break;
5142 }
5143 }
5144 i++;
5145 }
5146 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5147 str = str_parms_to_str(reply);
5148 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005149 voice_extn_out_get_parameters(out, query, reply);
5150 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005151 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005152
Alexy Joseph62142aa2015-11-16 15:10:34 -08005153
5154 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5155 if (ret >= 0) {
5156 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305157 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5158 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005159 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305160 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005161 } else {
5162 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305163 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005164 }
5165 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005166 if (str)
5167 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005168 str = str_parms_to_str(reply);
5169 }
5170
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005171 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5172 if (ret >= 0) {
5173 value[0] = '\0';
5174 i = 0;
5175 first = true;
5176 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005177 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5178 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005179 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005180 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005181 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005182 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005183 first = false;
5184 break;
5185 }
5186 }
5187 i++;
5188 }
5189 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005190 if (str)
5191 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005192 str = str_parms_to_str(reply);
5193 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005194
5195 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5196 if (ret >= 0) {
5197 value[0] = '\0';
5198 i = 0;
5199 first = true;
5200 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005201 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5202 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005203 if (!first) {
5204 strlcat(value, "|", sizeof(value));
5205 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005206 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005207 first = false;
5208 break;
5209 }
5210 }
5211 i++;
5212 }
5213 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5214 if (str)
5215 free(str);
5216 str = str_parms_to_str(reply);
5217 }
5218
Alexy Joseph98988832017-01-13 14:56:59 -08005219 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5220 //only low latency track supports suspend_resume
5221 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005222 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005223 if (str)
5224 free(str);
5225 str = str_parms_to_str(reply);
5226 }
5227
5228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005229 str_parms_destroy(query);
5230 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005231 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005232 return str;
5233}
5234
5235static uint32_t out_get_latency(const struct audio_stream_out *stream)
5236{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005237 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005238 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005239 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005240
Alexy Josephaa54c872014-12-03 02:46:47 -08005241 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305242 lock_output_stream(out);
5243 latency = audio_extn_utils_compress_get_dsp_latency(out);
5244 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005245 } else if ((out->realtime) ||
5246 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005247 // since the buffer won't be filled up faster than realtime,
5248 // return a smaller number
5249 if (out->config.rate)
5250 period_ms = (out->af_period_multiplier * out->config.period_size *
5251 1000) / (out->config.rate);
5252 else
5253 period_ms = 0;
5254 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005255 } else {
5256 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005257 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005258 }
5259
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005260 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005261 latency += audio_extn_a2dp_get_encoder_latency();
5262
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305263 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005264 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005265}
5266
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305267static float AmpToDb(float amplification)
5268{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305269 float db = DSD_VOLUME_MIN_DB;
5270 if (amplification > 0) {
5271 db = 20 * log10(amplification);
5272 if(db < DSD_VOLUME_MIN_DB)
5273 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305274 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305275 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305276}
5277
Arun Mirpuri5d170872019-03-26 13:21:31 -07005278static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5279 float right)
5280{
5281 struct stream_out *out = (struct stream_out *)stream;
5282 long volume = 0;
5283 char mixer_ctl_name[128] = "";
5284 struct audio_device *adev = out->dev;
5285 struct mixer_ctl *ctl = NULL;
5286 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5287 PCM_PLAYBACK);
5288
5289 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5290 "Playback %d Volume", pcm_device_id);
5291 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5292 if (!ctl) {
5293 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5294 __func__, mixer_ctl_name);
5295 return -EINVAL;
5296 }
5297 if (left != right)
5298 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5299 __func__, left, right);
5300 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5301 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5302 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5303 __func__, mixer_ctl_name, volume);
5304 return -EINVAL;
5305 }
5306 return 0;
5307}
5308
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305309static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5310 float right)
5311{
5312 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305313 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305314 char mixer_ctl_name[128];
5315 struct audio_device *adev = out->dev;
5316 struct mixer_ctl *ctl;
5317 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5318 PCM_PLAYBACK);
5319
5320 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5321 "Compress Playback %d Volume", pcm_device_id);
5322 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5323 if (!ctl) {
5324 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5325 __func__, mixer_ctl_name);
5326 return -EINVAL;
5327 }
5328 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5329 __func__, mixer_ctl_name, left, right);
5330 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5331 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5332 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5333
5334 return 0;
5335}
5336
Zhou Song2b8f28f2017-09-11 10:51:38 +08005337static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5338 float right)
5339{
5340 struct stream_out *out = (struct stream_out *)stream;
5341 char mixer_ctl_name[] = "App Type Gain";
5342 struct audio_device *adev = out->dev;
5343 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305344 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005345
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005346 if (!is_valid_volume(left, right)) {
5347 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5348 __func__, left, right);
5349 return -EINVAL;
5350 }
5351
Zhou Song2b8f28f2017-09-11 10:51:38 +08005352 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5353 if (!ctl) {
5354 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5355 __func__, mixer_ctl_name);
5356 return -EINVAL;
5357 }
5358
5359 set_values[0] = 0; //0: Rx Session 1:Tx Session
5360 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305361 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5362 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005363
5364 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5365 return 0;
5366}
5367
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305368static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5369 float right)
5370{
5371 struct stream_out *out = (struct stream_out *)stream;
5372 /* Volume control for pcm playback */
5373 if (left != right) {
5374 return -EINVAL;
5375 } else {
5376 char mixer_ctl_name[128];
5377 struct audio_device *adev = out->dev;
5378 struct mixer_ctl *ctl;
5379 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5380 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5381 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5382 if (!ctl) {
5383 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5384 return -EINVAL;
5385 }
5386
5387 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5388 int ret = mixer_ctl_set_value(ctl, 0, volume);
5389 if (ret < 0) {
5390 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5391 return -EINVAL;
5392 }
5393
5394 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5395
5396 return 0;
5397 }
5398}
5399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005400static int out_set_volume(struct audio_stream_out *stream, float left,
5401 float right)
5402{
Eric Laurenta9024de2013-04-04 09:19:12 -07005403 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005404 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305405 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005406
Arun Mirpuri5d170872019-03-26 13:21:31 -07005407 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005408 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5409 /* only take left channel into account: the API is for stereo anyway */
5410 out->muted = (left == 0.0f);
5411 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005412 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305413 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005414 /*
5415 * Set mute or umute on HDMI passthrough stream.
5416 * Only take left channel into account.
5417 * Mute is 0 and unmute 1
5418 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305419 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305420 } else if (out->format == AUDIO_FORMAT_DSD){
5421 char mixer_ctl_name[128] = "DSD Volume";
5422 struct audio_device *adev = out->dev;
5423 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5424
5425 if (!ctl) {
5426 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5427 __func__, mixer_ctl_name);
5428 return -EINVAL;
5429 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305430 volume[0] = (long)(AmpToDb(left));
5431 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305432 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5433 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005434 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005435 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005436 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5437 struct listnode *node = NULL;
5438 list_for_each(node, &adev->active_outputs_list) {
5439 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5440 streams_output_ctxt_t,
5441 list);
5442 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5443 out->volume_l = out_ctxt->output->volume_l;
5444 out->volume_r = out_ctxt->output->volume_r;
5445 }
5446 }
5447 if (!out->a2dp_compress_mute) {
5448 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5449 }
5450 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005451 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305452 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005453 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305454 if (!out->a2dp_compress_mute)
5455 ret = out_set_compr_volume(stream, left, right);
5456 out->volume_l = left;
5457 out->volume_r = right;
5458 pthread_mutex_unlock(&out->compr_mute_lock);
5459 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005460 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005461 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005462 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5463 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5464 if (!out->standby) {
5465 audio_extn_utils_send_app_type_gain(out->dev,
5466 out->app_type_cfg.app_type,
5467 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005468 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005469 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005470 out->volume_l = left;
5471 out->volume_r = right;
5472 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005473 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5474 ALOGV("%s: MMAP set volume called", __func__);
5475 if (!out->standby)
5476 ret = out_set_mmap_volume(stream, left, right);
5477 out->volume_l = left;
5478 out->volume_r = right;
5479 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305480 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305481 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5482 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305483 /* Volume control for pcm playback */
5484 if (!out->standby)
5485 ret = out_set_pcm_volume(stream, left, right);
5486 else
5487 out->apply_volume = true;
5488
5489 out->volume_l = left;
5490 out->volume_r = right;
5491 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005492 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5493 ALOGV("%s: bus device set volume called", __func__);
5494 if (!out->standby)
5495 ret = out_set_pcm_volume(stream, left, right);
5496 out->volume_l = left;
5497 out->volume_r = right;
5498 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005499 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005501 return -ENOSYS;
5502}
5503
Zhou Songc9672822017-08-16 16:01:39 +08005504static void update_frames_written(struct stream_out *out, size_t bytes)
5505{
5506 size_t bpf = 0;
5507
5508 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5509 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5510 bpf = 1;
5511 else if (!is_offload_usecase(out->usecase))
5512 bpf = audio_bytes_per_sample(out->format) *
5513 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005514
5515 pthread_mutex_lock(&out->position_query_lock);
5516 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005517 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005518 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5519 }
5520 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005521}
5522
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005523int split_and_write_audio_haptic_data(struct stream_out *out,
5524 const void *buffer, size_t bytes_to_write)
5525{
5526 struct audio_device *adev = out->dev;
5527
5528 int ret = 0;
5529 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5530 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5531 size_t frame_size = channel_count * bytes_per_sample;
5532 size_t frame_count = bytes_to_write / frame_size;
5533
5534 bool force_haptic_path =
5535 property_get_bool("vendor.audio.test_haptic", false);
5536
5537 // extract Haptics data from Audio buffer
5538 bool alloc_haptic_buffer = false;
5539 int haptic_channel_count = adev->haptics_config.channels;
5540 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5541 size_t audio_frame_size = frame_size - haptic_frame_size;
5542 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5543
5544 if (adev->haptic_buffer == NULL) {
5545 alloc_haptic_buffer = true;
5546 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5547 free(adev->haptic_buffer);
5548 adev->haptic_buffer_size = 0;
5549 alloc_haptic_buffer = true;
5550 }
5551
5552 if (alloc_haptic_buffer) {
5553 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005554 if(adev->haptic_buffer == NULL) {
5555 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5556 return -ENOMEM;
5557 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005558 adev->haptic_buffer_size = total_haptic_buffer_size;
5559 }
5560
5561 size_t src_index = 0, aud_index = 0, hap_index = 0;
5562 uint8_t *audio_buffer = (uint8_t *)buffer;
5563 uint8_t *haptic_buffer = adev->haptic_buffer;
5564
5565 // This is required for testing only. This works for stereo data only.
5566 // One channel is fed to audio stream and other to haptic stream for testing.
5567 if (force_haptic_path)
5568 audio_frame_size = haptic_frame_size = bytes_per_sample;
5569
5570 for (size_t i = 0; i < frame_count; i++) {
5571 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5572 audio_frame_size);
5573 aud_index += audio_frame_size;
5574 src_index += audio_frame_size;
5575
5576 if (adev->haptic_pcm)
5577 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5578 haptic_frame_size);
5579 hap_index += haptic_frame_size;
5580 src_index += haptic_frame_size;
5581
5582 // This is required for testing only.
5583 // Discard haptic channel data.
5584 if (force_haptic_path)
5585 src_index += haptic_frame_size;
5586 }
5587
5588 // write to audio pipeline
5589 ret = pcm_write(out->pcm, (void *)audio_buffer,
5590 frame_count * audio_frame_size);
5591
5592 // write to haptics pipeline
5593 if (adev->haptic_pcm)
5594 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5595 frame_count * haptic_frame_size);
5596
5597 return ret;
5598}
5599
Aalique Grahame22e49102018-12-18 14:23:57 -08005600#ifdef NO_AUDIO_OUT
5601static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5602 const void *buffer __unused, size_t bytes)
5603{
5604 struct stream_out *out = (struct stream_out *)stream;
5605
5606 /* No Output device supported other than BT for playback.
5607 * Sleep for the amount of buffer duration
5608 */
5609 lock_output_stream(out);
5610 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5611 (const struct audio_stream_out *)&out->stream) /
5612 out_get_sample_rate(&out->stream.common));
5613 pthread_mutex_unlock(&out->lock);
5614 return bytes;
5615}
5616#endif
5617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005618static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5619 size_t bytes)
5620{
5621 struct stream_out *out = (struct stream_out *)stream;
5622 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005623 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305624 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005625 const size_t frame_size = audio_stream_out_frame_size(stream);
5626 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305627 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005628 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005629
Haynes Mathew George380745d2017-10-04 15:27:45 -07005630 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005631 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305632
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305633 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005634
Dhananjay Kumarac341582017-02-23 23:42:25 +05305635 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305636 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305637 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5638 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005639 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305640 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305641 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305642 ALOGD(" %s: sound card is not active/SSR state", __func__);
5643 ret= -EIO;
5644 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305645 }
5646 }
5647
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305648 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305649 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305650 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305651 goto exit;
5652 }
5653
Haynes Mathew George16081042017-05-31 17:16:49 -07005654 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5655 ret = -EINVAL;
5656 goto exit;
5657 }
5658
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005659 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305660 !out->is_iec61937_info_available) {
5661
5662 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5663 out->is_iec61937_info_available = true;
5664 } else if (audio_extn_passthru_is_enabled()) {
5665 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305666 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305667
5668 if((out->format == AUDIO_FORMAT_DTS) ||
5669 (out->format == AUDIO_FORMAT_DTS_HD)) {
5670 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5671 buffer, bytes);
5672 if (ret) {
5673 if (ret != -ENOSYS) {
5674 out->is_iec61937_info_available = false;
5675 ALOGD("iec61937 transmission info not yet updated retry");
5676 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305677 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305678 /* if stream has started and after that there is
5679 * stream config change (iec transmission config)
5680 * then trigger select_device to update backend configuration.
5681 */
5682 out->stream_config_changed = true;
5683 pthread_mutex_lock(&adev->lock);
5684 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305685 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005686 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305687 ret = -EINVAL;
5688 goto exit;
5689 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305690 pthread_mutex_unlock(&adev->lock);
5691 out->stream_config_changed = false;
5692 out->is_iec61937_info_available = true;
5693 }
5694 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305695
Meng Wang4c32fb42020-01-16 17:57:11 +08005696#ifdef AUDIO_GKI_ENABLED
5697 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5698 compr_passthr = out->compr_config.codec->reserved[0];
5699#else
5700 compr_passthr = out->compr_config.codec->compr_passthr;
5701#endif
5702
Garmond Leung317cbf12017-09-13 16:20:50 -07005703 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005704 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305705 (out->is_iec61937_info_available == true)) {
5706 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5707 ret = -EINVAL;
5708 goto exit;
5709 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305710 }
5711 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305712
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005713 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005714 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005715 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5716 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305717 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305718 ret = -EIO;
5719 goto exit;
5720 }
5721 }
5722 }
5723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005724 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005725 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005726 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5727
Eric Laurent150dbfe2013-02-27 14:31:02 -08005728 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005729 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5730 ret = voice_extn_compress_voip_start_output_stream(out);
5731 else
5732 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005733 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005734 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005735 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005736 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005737 goto exit;
5738 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305739 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005740 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
vivek mehtab72d08d2016-04-29 03:16:47 -07005741 if (last_known_cal_step != -1) {
5742 ALOGD("%s: retry previous failed cal level set", __func__);
5743 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305744 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005745 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305746
5747 if ((out->is_iec61937_info_available == true) &&
5748 (audio_extn_passthru_is_passthrough_stream(out))&&
5749 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5750 ret = -EINVAL;
5751 goto exit;
5752 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305753 if (out->set_dual_mono)
5754 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005755
5756 // log startup time in ms.
5757 simple_stats_log(
5758 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005759 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005760
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005761 if (adev->is_channel_status_set == false &&
5762 compare_device_type(&out->device_list,
5763 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005764 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305765 adev->is_channel_status_set = true;
5766 }
5767
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305768 if ((adev->use_old_pspd_mix_ctrl == true) &&
5769 (out->pspd_coeff_sent == false)) {
5770 /*
5771 * Need to resend pspd coefficients after stream started for
5772 * older kernel version as it does not save the coefficients
5773 * and also stream has to be started for coeff to apply.
5774 */
5775 usecase = get_usecase_from_list(adev, out->usecase);
5776 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305777 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305778 out->pspd_coeff_sent = true;
5779 }
5780 }
5781
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005782 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005783 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005784 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005785 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005786 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5787 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305788 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5789 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005790 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305791 out->send_next_track_params = false;
5792 out->is_compr_metadata_avail = false;
5793 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005794 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305795 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305796 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005797
Ashish Jain83a6cc22016-06-28 14:34:17 +05305798 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305799 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305800 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305801 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005802 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305803 return -EINVAL;
5804 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305805 audio_format_t dst_format = out->hal_op_format;
5806 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305807
Dieter Luecking5d57def2018-09-07 14:23:37 +02005808 /* prevent division-by-zero */
5809 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5810 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5811 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5812 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305813 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005814 ATRACE_END();
5815 return -EINVAL;
5816 }
5817
Ashish Jainf1eaa582016-05-23 20:54:24 +05305818 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5819 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5820
Ashish Jain83a6cc22016-06-28 14:34:17 +05305821 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305822 dst_format,
5823 buffer,
5824 src_format,
5825 frames);
5826
Ashish Jain83a6cc22016-06-28 14:34:17 +05305827 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305828 bytes_to_write);
5829
5830 /*Convert written bytes in audio flinger format*/
5831 if (ret > 0)
5832 ret = ((ret * format_to_bitwidth_table[out->format]) /
5833 format_to_bitwidth_table[dst_format]);
5834 }
5835 } else
5836 ret = compress_write(out->compr, buffer, bytes);
5837
Zhou Songc9672822017-08-16 16:01:39 +08005838 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5839 update_frames_written(out, bytes);
5840
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305841 if (ret < 0)
5842 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005843 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305844 /*msg to cb thread only if non blocking write is enabled*/
5845 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305846 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005847 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305848 } else if (-ENETRESET == ret) {
5849 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305850 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305851 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305852 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005853 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305854 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005855 }
Ashish Jain5106d362016-05-11 19:23:33 +05305856
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305857 /* Call compr start only when non-zero bytes of data is there to be rendered */
5858 if (!out->playback_started && ret > 0) {
5859 int status = compress_start(out->compr);
5860 if (status < 0) {
5861 ret = status;
5862 ALOGE("%s: compr start failed with err %d", __func__, errno);
5863 goto exit;
5864 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005865 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005866 out->playback_started = 1;
5867 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005868
5869 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5870 popcount(out->channel_mask),
5871 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005872 }
5873 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005874 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005875 return ret;
5876 } else {
5877 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005878 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005879 if (out->muted)
5880 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005881 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5882 __func__, frames, frame_size, bytes_to_write);
5883
Aalique Grahame22e49102018-12-18 14:23:57 -08005884 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005885 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5886 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5887 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005888 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5889 int16_t *src = (int16_t *)buffer;
5890 int16_t *dst = (int16_t *)buffer;
5891
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005892 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005893 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005894 "out_write called for %s use case with wrong properties",
5895 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005896
5897 /*
5898 * FIXME: this can be removed once audio flinger mixer supports
5899 * mono output
5900 */
5901
5902 /*
5903 * Code below goes over each frame in the buffer and adds both
5904 * L and R samples and then divides by 2 to convert to mono
5905 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005906 if (channel_count == 2) {
5907 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5908 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5909 }
5910 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005911 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005912 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07005913
5914 // Note: since out_get_presentation_position() is called alternating with out_write()
5915 // by AudioFlinger, we can check underruns using the prior timestamp read.
5916 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
5917 if (out->last_fifo_valid) {
5918 // compute drain to see if there is an underrun.
5919 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
5920 const int64_t frames_by_time =
5921 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
5922 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
5923
5924 if (underrun > 0) {
5925 simple_stats_log(&out->fifo_underruns, underrun);
5926
5927 ALOGW("%s: underrun(%lld) "
5928 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
5929 __func__,
5930 (long long)out->fifo_underruns.n,
5931 (long long)frames_by_time,
5932 (long long)out->last_fifo_frames_remaining);
5933 }
5934 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
5935 }
5936
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305937 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005938
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005939 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005940
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005941 if (out->config.rate)
5942 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5943 out->config.rate;
5944
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005945 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005946 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5947
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005948 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005949 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005950 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305951 out->convert_buffer != NULL) {
5952
5953 memcpy_by_audio_format(out->convert_buffer,
5954 out->hal_op_format,
5955 buffer,
5956 out->hal_ip_format,
5957 out->config.period_size * out->config.channels);
5958
5959 ret = pcm_write(out->pcm, out->convert_buffer,
5960 (out->config.period_size *
5961 out->config.channels *
5962 format_to_bitwidth_table[out->hal_op_format]));
5963 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305964 /*
5965 * To avoid underrun in DSP when the application is not pumping
5966 * data at required rate, check for the no. of bytes and ignore
5967 * pcm_write if it is less than actual buffer size.
5968 * It is a work around to a change in compress VOIP driver.
5969 */
5970 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5971 bytes < (out->config.period_size * out->config.channels *
5972 audio_bytes_per_sample(out->format))) {
5973 size_t voip_buf_size =
5974 out->config.period_size * out->config.channels *
5975 audio_bytes_per_sample(out->format);
5976 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5977 __func__, bytes, voip_buf_size);
5978 usleep(((uint64_t)voip_buf_size - bytes) *
5979 1000000 / audio_stream_out_frame_size(stream) /
5980 out_get_sample_rate(&out->stream.common));
5981 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005982 } else {
5983 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5984 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5985 else
5986 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5987 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305988 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005989
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005990 release_out_focus(out);
5991
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305992 if (ret < 0)
5993 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005994 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305995 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005996 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005997 }
5998
5999exit:
Zhou Songc9672822017-08-16 16:01:39 +08006000 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306001 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306002 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306003 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006004 pthread_mutex_unlock(&out->lock);
6005
6006 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006007 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006008 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306009 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306010 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306011 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306012 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306013 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306014 out->standby = true;
6015 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306016 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006017 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6018 /* prevent division-by-zero */
6019 uint32_t stream_size = audio_stream_out_frame_size(stream);
6020 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006021
Dieter Luecking5d57def2018-09-07 14:23:37 +02006022 if ((stream_size == 0) || (srate == 0)) {
6023 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6024 ATRACE_END();
6025 return -EINVAL;
6026 }
6027 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6028 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006029 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306030 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006031 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006032 return ret;
6033 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006034 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006035 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006036 return bytes;
6037}
6038
6039static int out_get_render_position(const struct audio_stream_out *stream,
6040 uint32_t *dsp_frames)
6041{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006042 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006043
6044 if (dsp_frames == NULL)
6045 return -EINVAL;
6046
6047 *dsp_frames = 0;
6048 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006049 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306050
6051 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6052 * this operation and adev_close_output_stream(where out gets reset).
6053 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306054 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006055 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306056 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006057 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306058 return 0;
6059 }
6060
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006061 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306062 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306063 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006064 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306065 if (ret < 0)
6066 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006067 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306068 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006069 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306070 if (-ENETRESET == ret) {
6071 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306072 out->card_status = CARD_STATUS_OFFLINE;
6073 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306074 } else if(ret < 0) {
6075 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306076 ret = -EINVAL;
6077 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306078 /*
6079 * Handle corner case where compress session is closed during SSR
6080 * and timestamp is queried
6081 */
6082 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306083 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306084 } else if (out->prev_card_status_offline) {
6085 ALOGE("ERROR: previously sound card was offline,return error");
6086 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306087 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306088 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006089 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306090 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306091 pthread_mutex_unlock(&out->lock);
6092 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006093 } else if (audio_is_linear_pcm(out->format)) {
6094 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006095 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006096 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006097 } else
6098 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006099}
6100
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006101static int out_add_audio_effect(const struct audio_stream *stream __unused,
6102 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006103{
6104 return 0;
6105}
6106
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006107static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6108 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006109{
6110 return 0;
6111}
6112
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006113static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6114 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006115{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306116 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006117}
6118
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006119static int out_get_presentation_position(const struct audio_stream_out *stream,
6120 uint64_t *frames, struct timespec *timestamp)
6121{
6122 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306123 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006124 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006125
Ashish Jain5106d362016-05-11 19:23:33 +05306126 /* below piece of code is not guarded against any lock because audioFliner serializes
6127 * this operation and adev_close_output_stream( where out gets reset).
6128 */
6129 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306130 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006131 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306132 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6133 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6134 return 0;
6135 }
6136
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006137 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006138
Ashish Jain5106d362016-05-11 19:23:33 +05306139 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6140 ret = compress_get_tstamp(out->compr, &dsp_frames,
6141 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006142 // Adjustment accounts for A2dp encoder latency with offload usecases
6143 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006144 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006145 unsigned long offset =
6146 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6147 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6148 }
Ashish Jain5106d362016-05-11 19:23:33 +05306149 ALOGVV("%s rendered frames %ld sample_rate %d",
6150 __func__, dsp_frames, out->sample_rate);
6151 *frames = dsp_frames;
6152 if (ret < 0)
6153 ret = -errno;
6154 if (-ENETRESET == ret) {
6155 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306156 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306157 ret = -EINVAL;
6158 } else
6159 ret = 0;
6160 /* this is the best we can do */
6161 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006162 } else {
6163 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006164 unsigned int avail;
6165 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006166 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006167 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006168
Andy Hunga1f48fa2019-07-01 18:14:53 -07006169 if (out->kernel_buffer_size > avail) {
6170 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6171 } else {
6172 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6173 __func__, avail, out->kernel_buffer_size);
6174 avail = out->kernel_buffer_size;
6175 frames_temp = out->last_fifo_frames_remaining = 0;
6176 }
6177 out->last_fifo_valid = true;
6178 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6179
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006180 if (out->written >= frames_temp)
6181 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006182
Andy Hunga1f48fa2019-07-01 18:14:53 -07006183 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6184 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6185
Weiyin Jiangd4633762018-03-16 12:05:03 +08006186 // This adjustment accounts for buffering after app processor.
6187 // It is based on estimated DSP latency per use case, rather than exact.
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006188 frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL;
6189 if (signed_frames >= frames_temp)
6190 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006191
Weiyin Jiangd4633762018-03-16 12:05:03 +08006192 // Adjustment accounts for A2dp encoder latency with non offload usecases
6193 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006194 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006195 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6196 if (signed_frames >= frames_temp)
6197 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006198 }
6199
6200 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006201 *frames = signed_frames;
6202 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006203 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006204 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6205 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006206 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306207 *frames = out->written;
6208 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306209 if (is_offload_usecase(out->usecase))
6210 ret = -EINVAL;
6211 else
6212 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006213 }
6214 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006215 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006216 return ret;
6217}
6218
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006219static int out_set_callback(struct audio_stream_out *stream,
6220 stream_callback_t callback, void *cookie)
6221{
6222 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006223 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006224
6225 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006226 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006227 out->client_callback = callback;
6228 out->client_cookie = cookie;
6229 if (out->adsp_hdlr_stream_handle) {
6230 ret = audio_extn_adsp_hdlr_stream_set_callback(
6231 out->adsp_hdlr_stream_handle,
6232 callback,
6233 cookie);
6234 if (ret)
6235 ALOGW("%s:adsp hdlr callback registration failed %d",
6236 __func__, ret);
6237 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006238 pthread_mutex_unlock(&out->lock);
6239 return 0;
6240}
6241
6242static int out_pause(struct audio_stream_out* stream)
6243{
6244 struct stream_out *out = (struct stream_out *)stream;
6245 int status = -ENOSYS;
6246 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006247 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006248 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306249 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006250 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006251 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306252 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306253 status = compress_pause(out->compr);
6254
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006255 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006256
Mingming Yin21854652016-04-13 11:54:02 -07006257 if (audio_extn_passthru_is_active()) {
6258 ALOGV("offload use case, pause passthru");
6259 audio_extn_passthru_on_pause(out);
6260 }
6261
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306262 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006263 audio_extn_dts_notify_playback_state(out->usecase, 0,
6264 out->sample_rate, popcount(out->channel_mask),
6265 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006266 }
6267 pthread_mutex_unlock(&out->lock);
6268 }
6269 return status;
6270}
6271
6272static int out_resume(struct audio_stream_out* stream)
6273{
6274 struct stream_out *out = (struct stream_out *)stream;
6275 int status = -ENOSYS;
6276 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006277 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006278 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306279 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006280 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006281 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306282 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306283 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006284 }
6285 if (!status) {
6286 out->offload_state = OFFLOAD_STATE_PLAYING;
6287 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306288 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006289 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6290 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006291 }
6292 pthread_mutex_unlock(&out->lock);
6293 }
6294 return status;
6295}
6296
6297static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6298{
6299 struct stream_out *out = (struct stream_out *)stream;
6300 int status = -ENOSYS;
6301 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006302 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006303 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006304 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6305 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6306 else
6307 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6308 pthread_mutex_unlock(&out->lock);
6309 }
6310 return status;
6311}
6312
6313static int out_flush(struct audio_stream_out* stream)
6314{
6315 struct stream_out *out = (struct stream_out *)stream;
6316 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006317 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006318 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006319 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006320 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6321 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006322 } else {
6323 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6324 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006325 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006326 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006327 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006328 return 0;
6329 }
6330 return -ENOSYS;
6331}
6332
Haynes Mathew George16081042017-05-31 17:16:49 -07006333static int out_stop(const struct audio_stream_out* stream)
6334{
6335 struct stream_out *out = (struct stream_out *)stream;
6336 struct audio_device *adev = out->dev;
6337 int ret = -ENOSYS;
6338
6339 ALOGV("%s", __func__);
6340 pthread_mutex_lock(&adev->lock);
6341 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6342 out->playback_started && out->pcm != NULL) {
6343 pcm_stop(out->pcm);
6344 ret = stop_output_stream(out);
6345 out->playback_started = false;
6346 }
6347 pthread_mutex_unlock(&adev->lock);
6348 return ret;
6349}
6350
6351static int out_start(const struct audio_stream_out* stream)
6352{
6353 struct stream_out *out = (struct stream_out *)stream;
6354 struct audio_device *adev = out->dev;
6355 int ret = -ENOSYS;
6356
6357 ALOGV("%s", __func__);
6358 pthread_mutex_lock(&adev->lock);
6359 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6360 !out->playback_started && out->pcm != NULL) {
6361 ret = start_output_stream(out);
6362 if (ret == 0) {
6363 out->playback_started = true;
6364 }
6365 }
6366 pthread_mutex_unlock(&adev->lock);
6367 return ret;
6368}
6369
6370/*
6371 * Modify config->period_count based on min_size_frames
6372 */
6373static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6374{
6375 int periodCountRequested = (min_size_frames + config->period_size - 1)
6376 / config->period_size;
6377 int periodCount = MMAP_PERIOD_COUNT_MIN;
6378
6379 ALOGV("%s original config.period_size = %d config.period_count = %d",
6380 __func__, config->period_size, config->period_count);
6381
6382 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6383 periodCount *= 2;
6384 }
6385 config->period_count = periodCount;
6386
6387 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6388}
6389
Phil Burkfe17efd2019-03-25 10:23:35 -07006390// Read offset for the positional timestamp from a persistent vendor property.
6391// This is to workaround apparent inaccuracies in the timing information that
6392// is used by the AAudio timing model. The inaccuracies can cause glitches.
6393static int64_t get_mmap_out_time_offset() {
6394 const int32_t kDefaultOffsetMicros = 0;
6395 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006396 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006397 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6398 return mmap_time_offset_micros * (int64_t)1000;
6399}
6400
Haynes Mathew George16081042017-05-31 17:16:49 -07006401static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6402 int32_t min_size_frames,
6403 struct audio_mmap_buffer_info *info)
6404{
6405 struct stream_out *out = (struct stream_out *)stream;
6406 struct audio_device *adev = out->dev;
6407 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006408 unsigned int offset1 = 0;
6409 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006410 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006411 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006412 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006413
Arun Mirpuri5d170872019-03-26 13:21:31 -07006414 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306415 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006416 pthread_mutex_lock(&adev->lock);
6417
Sharad Sanglec6f32552018-05-04 16:15:38 +05306418 if (CARD_STATUS_OFFLINE == out->card_status ||
6419 CARD_STATUS_OFFLINE == adev->card_status) {
6420 ALOGW("out->card_status or adev->card_status offline, try again");
6421 ret = -EIO;
6422 goto exit;
6423 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306424 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006425 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6426 ret = -EINVAL;
6427 goto exit;
6428 }
6429 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6430 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6431 ret = -ENOSYS;
6432 goto exit;
6433 }
6434 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6435 if (out->pcm_device_id < 0) {
6436 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6437 __func__, out->pcm_device_id, out->usecase);
6438 ret = -EINVAL;
6439 goto exit;
6440 }
6441
6442 adjust_mmap_period_count(&out->config, min_size_frames);
6443
Arun Mirpuri5d170872019-03-26 13:21:31 -07006444 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006445 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6446 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6447 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306448 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306449 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6450 out->card_status = CARD_STATUS_OFFLINE;
6451 adev->card_status = CARD_STATUS_OFFLINE;
6452 ret = -EIO;
6453 goto exit;
6454 }
6455
Haynes Mathew George16081042017-05-31 17:16:49 -07006456 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6457 step = "open";
6458 ret = -ENODEV;
6459 goto exit;
6460 }
6461 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6462 if (ret < 0) {
6463 step = "begin";
6464 goto exit;
6465 }
juyuchen626833d2019-06-04 16:48:02 +08006466
6467 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006468 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006469 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006470 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006471 ret = platform_get_mmap_data_fd(adev->platform,
6472 out->pcm_device_id, 0 /*playback*/,
6473 &info->shared_memory_fd,
6474 &mmap_size);
6475 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006476 // Fall back to non exclusive mode
6477 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6478 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006479 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6480 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6481
Arun Mirpuri5d170872019-03-26 13:21:31 -07006482 if (mmap_size < buffer_size) {
6483 step = "mmap";
6484 goto exit;
6485 }
juyuchen626833d2019-06-04 16:48:02 +08006486 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006487 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006488 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006489 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006490
6491 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6492 if (ret < 0) {
6493 step = "commit";
6494 goto exit;
6495 }
6496
Phil Burkfe17efd2019-03-25 10:23:35 -07006497 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6498
Haynes Mathew George16081042017-05-31 17:16:49 -07006499 out->standby = false;
6500 ret = 0;
6501
Arun Mirpuri5d170872019-03-26 13:21:31 -07006502 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006503 __func__, info->shared_memory_address, info->buffer_size_frames);
6504
6505exit:
6506 if (ret != 0) {
6507 if (out->pcm == NULL) {
6508 ALOGE("%s: %s - %d", __func__, step, ret);
6509 } else {
6510 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6511 pcm_close(out->pcm);
6512 out->pcm = NULL;
6513 }
6514 }
6515 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306516 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006517 return ret;
6518}
6519
6520static int out_get_mmap_position(const struct audio_stream_out *stream,
6521 struct audio_mmap_position *position)
6522{
6523 struct stream_out *out = (struct stream_out *)stream;
6524 ALOGVV("%s", __func__);
6525 if (position == NULL) {
6526 return -EINVAL;
6527 }
6528 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006529 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006530 return -ENOSYS;
6531 }
6532 if (out->pcm == NULL) {
6533 return -ENOSYS;
6534 }
6535
6536 struct timespec ts = { 0, 0 };
6537 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6538 if (ret < 0) {
6539 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6540 return ret;
6541 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006542 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6543 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006544 return 0;
6545}
6546
6547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006548/** audio_stream_in implementation **/
6549static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6550{
6551 struct stream_in *in = (struct stream_in *)stream;
6552
6553 return in->config.rate;
6554}
6555
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006556static int in_set_sample_rate(struct audio_stream *stream __unused,
6557 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006558{
6559 return -ENOSYS;
6560}
6561
6562static size_t in_get_buffer_size(const struct audio_stream *stream)
6563{
6564 struct stream_in *in = (struct stream_in *)stream;
6565
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006566 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6567 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006568 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6569 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306570 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306571 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006572
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006573 return in->config.period_size * in->af_period_multiplier *
6574 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006575}
6576
6577static uint32_t in_get_channels(const struct audio_stream *stream)
6578{
6579 struct stream_in *in = (struct stream_in *)stream;
6580
6581 return in->channel_mask;
6582}
6583
6584static audio_format_t in_get_format(const struct audio_stream *stream)
6585{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006586 struct stream_in *in = (struct stream_in *)stream;
6587
6588 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006589}
6590
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006591static int in_set_format(struct audio_stream *stream __unused,
6592 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006593{
6594 return -ENOSYS;
6595}
6596
6597static int in_standby(struct audio_stream *stream)
6598{
6599 struct stream_in *in = (struct stream_in *)stream;
6600 struct audio_device *adev = in->dev;
6601 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306602 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6603 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006604 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306605
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006606 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006607 if (!in->standby && in->is_st_session) {
6608 ALOGD("%s: sound trigger pcm stop lab", __func__);
6609 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006610 if (adev->num_va_sessions > 0)
6611 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006612 in->standby = 1;
6613 }
6614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006615 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006616 if (adev->adm_deregister_stream)
6617 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6618
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006619 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006620 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006621 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006622 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006623 voice_extn_compress_voip_close_input_stream(stream);
6624 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006625 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6626 do_stop = in->capture_started;
6627 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006628 if (in->mmap_shared_memory_fd >= 0) {
6629 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6630 __func__, in->mmap_shared_memory_fd);
6631 close(in->mmap_shared_memory_fd);
6632 in->mmap_shared_memory_fd = -1;
6633 }
Zhou Songa8895042016-07-05 17:54:22 +08006634 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306635 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306636 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006637 }
6638
Arun Mirpuri5d170872019-03-26 13:21:31 -07006639 if (in->pcm) {
6640 ATRACE_BEGIN("pcm_in_close");
6641 pcm_close(in->pcm);
6642 ATRACE_END();
6643 in->pcm = NULL;
6644 }
6645
Carter Hsu2e429db2019-05-14 18:50:52 +08006646 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006647 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006648
George Gao3018ede2019-10-23 13:23:00 -07006649 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6650 if (adev->num_va_sessions > 0)
6651 adev->num_va_sessions--;
6652 }
Quinn Malef6050362019-01-30 15:55:40 -08006653
Eric Laurent150dbfe2013-02-27 14:31:02 -08006654 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006655 }
6656 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006657 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006658 return status;
6659}
6660
Aalique Grahame22e49102018-12-18 14:23:57 -08006661static int in_dump(const struct audio_stream *stream,
6662 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006663{
Aalique Grahame22e49102018-12-18 14:23:57 -08006664 struct stream_in *in = (struct stream_in *)stream;
6665
6666 // We try to get the lock for consistency,
6667 // but it isn't necessary for these variables.
6668 // If we're not in standby, we may be blocked on a read.
6669 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6670 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6671 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6672 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6673
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006674 char buffer[256]; // for statistics formatting
6675 if (in->start_latency_ms.n > 0) {
6676 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6677 dprintf(fd, " Start latency ms: %s\n", buffer);
6678 }
6679
Aalique Grahame22e49102018-12-18 14:23:57 -08006680 if (locked) {
6681 pthread_mutex_unlock(&in->lock);
6682 }
6683
6684 // dump error info
6685 (void)error_log_dump(
6686 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006688 return 0;
6689}
6690
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306691static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6692{
6693 if (!stream || !parms)
6694 return;
6695
6696 struct stream_in *in = (struct stream_in *)stream;
6697 struct audio_device *adev = in->dev;
6698
6699 card_status_t status;
6700 int card;
6701 if (parse_snd_card_status(parms, &card, &status) < 0)
6702 return;
6703
6704 pthread_mutex_lock(&adev->lock);
6705 bool valid_cb = (card == adev->snd_card);
6706 pthread_mutex_unlock(&adev->lock);
6707
6708 if (!valid_cb)
6709 return;
6710
6711 lock_input_stream(in);
6712 if (in->card_status != status)
6713 in->card_status = status;
6714 pthread_mutex_unlock(&in->lock);
6715
6716 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6717 use_case_table[in->usecase],
6718 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6719
6720 // a better solution would be to report error back to AF and let
6721 // it put the stream to standby
6722 if (status == CARD_STATUS_OFFLINE)
6723 in_standby(&in->stream.common);
6724
6725 return;
6726}
6727
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006728int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006729 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006730 audio_source_t source)
6731{
6732 struct audio_device *adev = in->dev;
6733 int ret = 0;
6734
6735 lock_input_stream(in);
6736 pthread_mutex_lock(&adev->lock);
6737
6738 /* no audio source uses val == 0 */
6739 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6740 in->source = source;
6741 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6742 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6743 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6744 (in->config.rate == 8000 || in->config.rate == 16000 ||
6745 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6746 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6747 ret = voice_extn_compress_voip_open_input_stream(in);
6748 if (ret != 0) {
6749 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6750 __func__, ret);
6751 }
6752 }
6753 }
6754
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006755 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6756 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006757 // Workaround: If routing to an non existing usb device, fail gracefully
6758 // The routing request will otherwise block during 10 second
6759 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006760 struct str_parms *usb_addr =
6761 str_parms_create_str(get_usb_device_address(devices));
6762 if (is_usb_in_device_type(devices) && usb_addr &&
6763 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006764 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6765 ret = -ENOSYS;
6766 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006767 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006768 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006769 if (!in->standby && !in->is_st_session) {
6770 ALOGV("update input routing change");
6771 // inform adm before actual routing to prevent glitches.
6772 if (adev->adm_on_routing_change) {
6773 adev->adm_on_routing_change(adev->adm_data,
6774 in->capture_handle);
6775 ret = select_devices(adev, in->usecase);
6776 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6777 adev->adm_routing_changed = true;
6778 }
6779 }
6780 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006781 if (usb_addr)
6782 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006783 }
6784 pthread_mutex_unlock(&adev->lock);
6785 pthread_mutex_unlock(&in->lock);
6786
6787 ALOGD("%s: exit: status(%d)", __func__, ret);
6788 return ret;
6789}
6790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006791static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6792{
6793 struct stream_in *in = (struct stream_in *)stream;
6794 struct audio_device *adev = in->dev;
6795 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006796 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306797 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006798
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306799 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006800 parms = str_parms_create_str(kvpairs);
6801
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306802 if (!parms)
6803 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006804 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006805 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006806
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306807 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6808 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306809 strlcpy(in->profile, value, sizeof(in->profile));
6810 ALOGV("updating stream profile with value '%s'", in->profile);
6811 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6812 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006813 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306814 in->sample_rate, in->bit_width,
6815 in->profile, &in->app_type_cfg);
6816 }
6817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006818 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006819 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006820
6821 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306822error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306823 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006824}
6825
6826static char* in_get_parameters(const struct audio_stream *stream,
6827 const char *keys)
6828{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006829 struct stream_in *in = (struct stream_in *)stream;
6830 struct str_parms *query = str_parms_create_str(keys);
6831 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006832 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006833
6834 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006835 if (reply) {
6836 str_parms_destroy(reply);
6837 }
6838 if (query) {
6839 str_parms_destroy(query);
6840 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006841 ALOGE("in_get_parameters: failed to create query or reply");
6842 return NULL;
6843 }
6844
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006845 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006846
6847 voice_extn_in_get_parameters(in, query, reply);
6848
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006849 stream_get_parameter_channels(query, reply,
6850 &in->supported_channel_masks[0]);
6851 stream_get_parameter_formats(query, reply,
6852 &in->supported_formats[0]);
6853 stream_get_parameter_rates(query, reply,
6854 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006855 str = str_parms_to_str(reply);
6856 str_parms_destroy(query);
6857 str_parms_destroy(reply);
6858
6859 ALOGV("%s: exit: returns - %s", __func__, str);
6860 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006861}
6862
Aalique Grahame22e49102018-12-18 14:23:57 -08006863static int in_set_gain(struct audio_stream_in *stream,
6864 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006865{
Aalique Grahame22e49102018-12-18 14:23:57 -08006866 struct stream_in *in = (struct stream_in *)stream;
6867 char mixer_ctl_name[128];
6868 struct mixer_ctl *ctl;
6869 int ctl_value;
6870
6871 ALOGV("%s: gain %f", __func__, gain);
6872
6873 if (stream == NULL)
6874 return -EINVAL;
6875
6876 /* in_set_gain() only used to silence MMAP capture for now */
6877 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6878 return -ENOSYS;
6879
6880 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6881
6882 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6883 if (!ctl) {
6884 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6885 __func__, mixer_ctl_name);
6886 return -ENOSYS;
6887 }
6888
6889 if (gain < RECORD_GAIN_MIN)
6890 gain = RECORD_GAIN_MIN;
6891 else if (gain > RECORD_GAIN_MAX)
6892 gain = RECORD_GAIN_MAX;
6893 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6894
6895 mixer_ctl_set_value(ctl, 0, ctl_value);
6896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006897 return 0;
6898}
6899
6900static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6901 size_t bytes)
6902{
6903 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306904
6905 if (in == NULL) {
6906 ALOGE("%s: stream_in ptr is NULL", __func__);
6907 return -EINVAL;
6908 }
6909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006910 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306911 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306912 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006913
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006914 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306915
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006916 if (in->is_st_session) {
6917 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6918 /* Read from sound trigger HAL */
6919 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006920 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006921 if (adev->num_va_sessions < UINT_MAX)
6922 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006923 in->standby = 0;
6924 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006925 pthread_mutex_unlock(&in->lock);
6926 return bytes;
6927 }
6928
Haynes Mathew George16081042017-05-31 17:16:49 -07006929 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6930 ret = -ENOSYS;
6931 goto exit;
6932 }
6933
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006934 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6935 !in->standby && adev->adm_routing_changed) {
6936 ret = -ENOSYS;
6937 goto exit;
6938 }
6939
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006940 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006941 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6942
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006943 pthread_mutex_lock(&adev->lock);
6944 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6945 ret = voice_extn_compress_voip_start_input_stream(in);
6946 else
6947 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006948 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6949 if (adev->num_va_sessions < UINT_MAX)
6950 adev->num_va_sessions++;
6951 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006952 pthread_mutex_unlock(&adev->lock);
6953 if (ret != 0) {
6954 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006955 }
6956 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006957
6958 // log startup time in ms.
6959 simple_stats_log(
6960 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006961 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006962
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306963 /* Avoid read if capture_stopped is set */
6964 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6965 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6966 ret = -EINVAL;
6967 goto exit;
6968 }
6969
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006970 // what's the duration requested by the client?
6971 long ns = 0;
6972
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306973 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006974 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6975 in->config.rate;
6976
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006977 ret = request_in_focus(in, ns);
6978 if (ret != 0)
6979 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006980 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006981
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306982 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306983 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6984 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306985 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006986 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306987 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006988 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006989 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006990 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006991 } else if (audio_extn_ffv_get_stream() == in) {
6992 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306993 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006994 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306995 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6996 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6997 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6998 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306999 ret = -EINVAL;
7000 goto exit;
7001 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307002 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307003 ret = -errno;
7004 }
7005 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307006 /* bytes read is always set to bytes for non compress usecases */
7007 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007008 }
7009
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007010 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007012 /*
Quinn Malef6050362019-01-30 15:55:40 -08007013 * Instead of writing zeroes here, we could trust the hardware to always
7014 * provide zeroes when muted. This is also muted with voice recognition
7015 * usecases so that other clients do not have access to voice recognition
7016 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007017 */
Quinn Malef6050362019-01-30 15:55:40 -08007018 if ((ret == 0 && voice_get_mic_mute(adev) &&
7019 !voice_is_in_call_rec_stream(in) &&
7020 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
7021 (adev->num_va_sessions &&
7022 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7023 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7024 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007025 memset(buffer, 0, bytes);
7026
7027exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307028 frame_size = audio_stream_in_frame_size(stream);
7029 if (frame_size > 0)
7030 in->frames_read += bytes_read/frame_size;
7031
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007032 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307033 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007034 pthread_mutex_unlock(&in->lock);
7035
7036 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307037 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307038 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307039 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307040 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307041 in->standby = true;
7042 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307043 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307044 bytes_read = bytes;
7045 memset(buffer, 0, bytes);
7046 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007047 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007048 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7049 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007050 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307051 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307052 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007053 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307054 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007055}
7056
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007057static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007058{
7059 return 0;
7060}
7061
Aalique Grahame22e49102018-12-18 14:23:57 -08007062static int in_get_capture_position(const struct audio_stream_in *stream,
7063 int64_t *frames, int64_t *time)
7064{
7065 if (stream == NULL || frames == NULL || time == NULL) {
7066 return -EINVAL;
7067 }
7068 struct stream_in *in = (struct stream_in *)stream;
7069 int ret = -ENOSYS;
7070
7071 lock_input_stream(in);
7072 // note: ST sessions do not close the alsa pcm driver synchronously
7073 // on standby. Therefore, we may return an error even though the
7074 // pcm stream is still opened.
7075 if (in->standby) {
7076 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7077 "%s stream in standby but pcm not NULL for non ST session", __func__);
7078 goto exit;
7079 }
7080 if (in->pcm) {
7081 struct timespec timestamp;
7082 unsigned int avail;
7083 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7084 *frames = in->frames_read + avail;
7085 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
7086 ret = 0;
7087 }
7088 }
7089exit:
7090 pthread_mutex_unlock(&in->lock);
7091 return ret;
7092}
7093
Carter Hsu2e429db2019-05-14 18:50:52 +08007094static int in_update_effect_list(bool add, effect_handle_t effect,
7095 struct listnode *head)
7096{
7097 struct listnode *node;
7098 struct in_effect_list *elist = NULL;
7099 struct in_effect_list *target = NULL;
7100 int ret = 0;
7101
7102 if (!head)
7103 return ret;
7104
7105 list_for_each(node, head) {
7106 elist = node_to_item(node, struct in_effect_list, list);
7107 if (elist->handle == effect) {
7108 target = elist;
7109 break;
7110 }
7111 }
7112
7113 if (add) {
7114 if (target) {
7115 ALOGD("effect %p already exist", effect);
7116 return ret;
7117 }
7118
7119 target = (struct in_effect_list *)
7120 calloc(1, sizeof(struct in_effect_list));
7121
7122 if (!target) {
7123 ALOGE("%s:fail to allocate memory", __func__);
7124 return -ENOMEM;
7125 }
7126
7127 target->handle = effect;
7128 list_add_tail(head, &target->list);
7129 } else {
7130 if (target) {
7131 list_remove(&target->list);
7132 free(target);
7133 }
7134 }
7135
7136 return ret;
7137}
7138
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007139static int add_remove_audio_effect(const struct audio_stream *stream,
7140 effect_handle_t effect,
7141 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007142{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007143 struct stream_in *in = (struct stream_in *)stream;
7144 int status = 0;
7145 effect_descriptor_t desc;
7146
7147 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007148 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7149
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007150 if (status != 0)
7151 return status;
7152
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007153 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007154 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007155 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007156 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7157 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007158 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007159
7160 in_update_effect_list(enable, effect, &in->aec_list);
7161 enable = !list_empty(&in->aec_list);
7162 if (enable == in->enable_aec)
7163 goto exit;
7164
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007165 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007166 ALOGD("AEC enable %d", enable);
7167
Aalique Grahame22e49102018-12-18 14:23:57 -08007168 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7169 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7170 in->dev->enable_voicerx = enable;
7171 struct audio_usecase *usecase;
7172 struct listnode *node;
7173 list_for_each(node, &in->dev->usecase_list) {
7174 usecase = node_to_item(node, struct audio_usecase, list);
7175 if (usecase->type == PCM_PLAYBACK)
7176 select_devices(in->dev, usecase->id);
7177 }
7178 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007179 if (!in->standby) {
7180 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7181 select_devices(in->dev, in->usecase);
7182 }
7183
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007184 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007185 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7186
7187 in_update_effect_list(enable, effect, &in->ns_list);
7188 enable = !list_empty(&in->ns_list);
7189 if (enable == in->enable_ns)
7190 goto exit;
7191
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007192 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007193 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007194 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007195 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7196 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007197 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7198 select_devices(in->dev, in->usecase);
7199 } else
7200 select_devices(in->dev, in->usecase);
7201 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007202 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007203exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007204 pthread_mutex_unlock(&in->dev->lock);
7205 pthread_mutex_unlock(&in->lock);
7206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007207 return 0;
7208}
7209
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007210static int in_add_audio_effect(const struct audio_stream *stream,
7211 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007212{
Eric Laurent994a6932013-07-17 11:51:42 -07007213 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007214 return add_remove_audio_effect(stream, effect, true);
7215}
7216
7217static int in_remove_audio_effect(const struct audio_stream *stream,
7218 effect_handle_t effect)
7219{
Eric Laurent994a6932013-07-17 11:51:42 -07007220 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007221 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007222}
7223
Derek Chenf939fb72018-11-13 13:34:41 -08007224streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7225 audio_io_handle_t input)
7226{
7227 struct listnode *node;
7228
7229 list_for_each(node, &dev->active_inputs_list) {
7230 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7231 streams_input_ctxt_t,
7232 list);
7233 if (in_ctxt->input->capture_handle == input) {
7234 return in_ctxt;
7235 }
7236 }
7237 return NULL;
7238}
7239
7240streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7241 audio_io_handle_t output)
7242{
7243 struct listnode *node;
7244
7245 list_for_each(node, &dev->active_outputs_list) {
7246 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7247 streams_output_ctxt_t,
7248 list);
7249 if (out_ctxt->output->handle == output) {
7250 return out_ctxt;
7251 }
7252 }
7253 return NULL;
7254}
7255
Haynes Mathew George16081042017-05-31 17:16:49 -07007256static int in_stop(const struct audio_stream_in* stream)
7257{
7258 struct stream_in *in = (struct stream_in *)stream;
7259 struct audio_device *adev = in->dev;
7260
7261 int ret = -ENOSYS;
7262 ALOGV("%s", __func__);
7263 pthread_mutex_lock(&adev->lock);
7264 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7265 in->capture_started && in->pcm != NULL) {
7266 pcm_stop(in->pcm);
7267 ret = stop_input_stream(in);
7268 in->capture_started = false;
7269 }
7270 pthread_mutex_unlock(&adev->lock);
7271 return ret;
7272}
7273
7274static int in_start(const struct audio_stream_in* stream)
7275{
7276 struct stream_in *in = (struct stream_in *)stream;
7277 struct audio_device *adev = in->dev;
7278 int ret = -ENOSYS;
7279
7280 ALOGV("%s in %p", __func__, in);
7281 pthread_mutex_lock(&adev->lock);
7282 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7283 !in->capture_started && in->pcm != NULL) {
7284 if (!in->capture_started) {
7285 ret = start_input_stream(in);
7286 if (ret == 0) {
7287 in->capture_started = true;
7288 }
7289 }
7290 }
7291 pthread_mutex_unlock(&adev->lock);
7292 return ret;
7293}
7294
Phil Burke0a86d12019-02-16 22:28:11 -08007295// Read offset for the positional timestamp from a persistent vendor property.
7296// This is to workaround apparent inaccuracies in the timing information that
7297// is used by the AAudio timing model. The inaccuracies can cause glitches.
7298static int64_t in_get_mmap_time_offset() {
7299 const int32_t kDefaultOffsetMicros = 0;
7300 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007301 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007302 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7303 return mmap_time_offset_micros * (int64_t)1000;
7304}
7305
Haynes Mathew George16081042017-05-31 17:16:49 -07007306static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7307 int32_t min_size_frames,
7308 struct audio_mmap_buffer_info *info)
7309{
7310 struct stream_in *in = (struct stream_in *)stream;
7311 struct audio_device *adev = in->dev;
7312 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007313 unsigned int offset1 = 0;
7314 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007315 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007316 uint32_t mmap_size = 0;
7317 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007318
7319 pthread_mutex_lock(&adev->lock);
7320 ALOGV("%s in %p", __func__, in);
7321
Sharad Sanglec6f32552018-05-04 16:15:38 +05307322 if (CARD_STATUS_OFFLINE == in->card_status||
7323 CARD_STATUS_OFFLINE == adev->card_status) {
7324 ALOGW("in->card_status or adev->card_status offline, try again");
7325 ret = -EIO;
7326 goto exit;
7327 }
7328
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307329 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007330 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7331 ret = -EINVAL;
7332 goto exit;
7333 }
7334 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7335 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7336 ALOGV("%s in %p", __func__, in);
7337 ret = -ENOSYS;
7338 goto exit;
7339 }
7340 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7341 if (in->pcm_device_id < 0) {
7342 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7343 __func__, in->pcm_device_id, in->usecase);
7344 ret = -EINVAL;
7345 goto exit;
7346 }
7347
7348 adjust_mmap_period_count(&in->config, min_size_frames);
7349
7350 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7351 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7352 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7353 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307354 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307355 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7356 in->card_status = CARD_STATUS_OFFLINE;
7357 adev->card_status = CARD_STATUS_OFFLINE;
7358 ret = -EIO;
7359 goto exit;
7360 }
7361
Haynes Mathew George16081042017-05-31 17:16:49 -07007362 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7363 step = "open";
7364 ret = -ENODEV;
7365 goto exit;
7366 }
7367
7368 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7369 if (ret < 0) {
7370 step = "begin";
7371 goto exit;
7372 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007373
juyuchen626833d2019-06-04 16:48:02 +08007374 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007375 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7376 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7377 info->burst_size_frames = in->config.period_size;
7378 ret = platform_get_mmap_data_fd(adev->platform,
7379 in->pcm_device_id, 1 /*capture*/,
7380 &info->shared_memory_fd,
7381 &mmap_size);
7382 if (ret < 0) {
7383 // Fall back to non exclusive mode
7384 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7385 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007386 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7387 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7388
Arun Mirpuri5d170872019-03-26 13:21:31 -07007389 if (mmap_size < buffer_size) {
7390 step = "mmap";
7391 goto exit;
7392 }
juyuchen626833d2019-06-04 16:48:02 +08007393 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007394 }
7395
7396 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007397
7398 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7399 if (ret < 0) {
7400 step = "commit";
7401 goto exit;
7402 }
7403
Phil Burke0a86d12019-02-16 22:28:11 -08007404 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7405
Haynes Mathew George16081042017-05-31 17:16:49 -07007406 in->standby = false;
7407 ret = 0;
7408
7409 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7410 __func__, info->shared_memory_address, info->buffer_size_frames);
7411
7412exit:
7413 if (ret != 0) {
7414 if (in->pcm == NULL) {
7415 ALOGE("%s: %s - %d", __func__, step, ret);
7416 } else {
7417 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7418 pcm_close(in->pcm);
7419 in->pcm = NULL;
7420 }
7421 }
7422 pthread_mutex_unlock(&adev->lock);
7423 return ret;
7424}
7425
7426static int in_get_mmap_position(const struct audio_stream_in *stream,
7427 struct audio_mmap_position *position)
7428{
7429 struct stream_in *in = (struct stream_in *)stream;
7430 ALOGVV("%s", __func__);
7431 if (position == NULL) {
7432 return -EINVAL;
7433 }
7434 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7435 return -ENOSYS;
7436 }
7437 if (in->pcm == NULL) {
7438 return -ENOSYS;
7439 }
7440 struct timespec ts = { 0, 0 };
7441 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7442 if (ret < 0) {
7443 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7444 return ret;
7445 }
Phil Burke0a86d12019-02-16 22:28:11 -08007446 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7447 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007448 return 0;
7449}
7450
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307451static int in_get_active_microphones(const struct audio_stream_in *stream,
7452 struct audio_microphone_characteristic_t *mic_array,
7453 size_t *mic_count) {
7454 struct stream_in *in = (struct stream_in *)stream;
7455 struct audio_device *adev = in->dev;
7456 ALOGVV("%s", __func__);
7457
7458 lock_input_stream(in);
7459 pthread_mutex_lock(&adev->lock);
7460 int ret = platform_get_active_microphones(adev->platform,
7461 audio_channel_count_from_in_mask(in->channel_mask),
7462 in->usecase, mic_array, mic_count);
7463 pthread_mutex_unlock(&adev->lock);
7464 pthread_mutex_unlock(&in->lock);
7465
7466 return ret;
7467}
7468
7469static int adev_get_microphones(const struct audio_hw_device *dev,
7470 struct audio_microphone_characteristic_t *mic_array,
7471 size_t *mic_count) {
7472 struct audio_device *adev = (struct audio_device *)dev;
7473 ALOGVV("%s", __func__);
7474
7475 pthread_mutex_lock(&adev->lock);
7476 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7477 pthread_mutex_unlock(&adev->lock);
7478
7479 return ret;
7480}
juyuchendb308c22019-01-21 11:57:17 -07007481
7482static void in_update_sink_metadata(struct audio_stream_in *stream,
7483 const struct sink_metadata *sink_metadata) {
7484
7485 if (stream == NULL
7486 || sink_metadata == NULL
7487 || sink_metadata->tracks == NULL) {
7488 return;
7489 }
7490
7491 int error = 0;
7492 struct stream_in *in = (struct stream_in *)stream;
7493 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007494 struct listnode devices;
7495
7496 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007497
7498 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007499 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007500
7501 lock_input_stream(in);
7502 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007503 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007504
7505 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007506 && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007507 && adev->voice_tx_output != NULL) {
7508 /* Use the rx device from afe-proxy record to route voice call because
7509 there is no routing if tx device is on primary hal and rx device
7510 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007511 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007512
7513 if (!voice_is_call_state_active(adev)) {
7514 if (adev->mode == AUDIO_MODE_IN_CALL) {
7515 adev->current_call_output = adev->voice_tx_output;
7516 error = voice_start_call(adev);
7517 if (error != 0)
7518 ALOGE("%s: start voice call failed %d", __func__, error);
7519 }
7520 } else {
7521 adev->current_call_output = adev->voice_tx_output;
7522 voice_update_devices_for_all_voice_usecases(adev);
7523 }
7524 }
7525
7526 pthread_mutex_unlock(&adev->lock);
7527 pthread_mutex_unlock(&in->lock);
7528}
7529
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307530int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007531 audio_io_handle_t handle,
7532 audio_devices_t devices,
7533 audio_output_flags_t flags,
7534 struct audio_config *config,
7535 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007536 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007537{
7538 struct audio_device *adev = (struct audio_device *)dev;
7539 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307540 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007541 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007542 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307543 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007544 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7545 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7546 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7547 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007548 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007549 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7550 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007551 bool force_haptic_path =
7552 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007553 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007554
kunleizdff872d2018-08-20 14:40:33 +08007555 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007556 is_usb_dev = false;
7557 devices = AUDIO_DEVICE_OUT_SPEAKER;
7558 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7559 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007560 if (config->format == AUDIO_FORMAT_DEFAULT)
7561 config->format = AUDIO_FORMAT_PCM_16_BIT;
7562 if (config->sample_rate == 0)
7563 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7564 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7565 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007566 }
7567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007568 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307569
Rahul Sharma99770982019-03-06 17:05:26 +05307570 pthread_mutex_lock(&adev->lock);
7571 if (out_get_stream(adev, handle) != NULL) {
7572 ALOGW("%s, output stream already opened", __func__);
7573 ret = -EEXIST;
7574 }
7575 pthread_mutex_unlock(&adev->lock);
7576 if (ret)
7577 return ret;
7578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007579 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7580
Mingming Yin3a941d42016-02-17 18:08:05 -08007581 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007582 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7583 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307584
7585
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007586 if (!out) {
7587 return -ENOMEM;
7588 }
7589
Haynes Mathew George204045b2015-02-25 20:32:03 -08007590 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007591 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307592 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007593 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007594 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7595
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007596 if (devices == AUDIO_DEVICE_NONE)
7597 devices = AUDIO_DEVICE_OUT_SPEAKER;
7598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007599 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007600 list_init(&out->device_list);
7601 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007602 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007603 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007604 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307605 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307606 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7607 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7608 else
7609 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007610 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007611 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007612 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307613 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307614 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307615 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007616 out->hal_output_suspend_supported = 0;
7617 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307618 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307619 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307620 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007621 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007622
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307623 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307624 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007625 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7626
Aalique Grahame22e49102018-12-18 14:23:57 -08007627 if (direct_dev &&
7628 (audio_is_linear_pcm(out->format) ||
7629 config->format == AUDIO_FORMAT_DEFAULT) &&
7630 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7631 audio_format_t req_format = config->format;
7632 audio_channel_mask_t req_channel_mask = config->channel_mask;
7633 uint32_t req_sample_rate = config->sample_rate;
7634
7635 pthread_mutex_lock(&adev->lock);
7636 if (is_hdmi) {
7637 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7638 ret = read_hdmi_sink_caps(out);
7639 if (config->sample_rate == 0)
7640 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7641 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7642 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7643 if (config->format == AUDIO_FORMAT_DEFAULT)
7644 config->format = AUDIO_FORMAT_PCM_16_BIT;
7645 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007646 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7647 &config->format,
7648 &out->supported_formats[0],
7649 MAX_SUPPORTED_FORMATS,
7650 &config->channel_mask,
7651 &out->supported_channel_masks[0],
7652 MAX_SUPPORTED_CHANNEL_MASKS,
7653 &config->sample_rate,
7654 &out->supported_sample_rates[0],
7655 MAX_SUPPORTED_SAMPLE_RATES);
7656 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007657 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007658
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007659 pthread_mutex_unlock(&adev->lock);
7660 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007661 if (ret == -ENOSYS) {
7662 /* ignore and go with default */
7663 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007664 }
7665 // For MMAP NO IRQ, allow conversions in ADSP
7666 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7667 goto error_open;
7668 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007669 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007670 goto error_open;
7671 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007672
7673 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7674 config->sample_rate = req_sample_rate;
7675 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7676 config->channel_mask = req_channel_mask;
7677 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7678 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007679 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007680
7681 out->sample_rate = config->sample_rate;
7682 out->channel_mask = config->channel_mask;
7683 out->format = config->format;
7684 if (is_hdmi) {
7685 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7686 out->config = pcm_config_hdmi_multi;
7687 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7688 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7689 out->config = pcm_config_mmap_playback;
7690 out->stream.start = out_start;
7691 out->stream.stop = out_stop;
7692 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7693 out->stream.get_mmap_position = out_get_mmap_position;
7694 } else {
7695 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7696 out->config = pcm_config_hifi;
7697 }
7698
7699 out->config.rate = out->sample_rate;
7700 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7701 if (is_hdmi) {
7702 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7703 audio_bytes_per_sample(out->format));
7704 }
7705 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007706 }
7707
Derek Chenf6318be2017-06-12 17:16:24 -04007708 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007709 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007710 /* extract car audio stream index */
7711 out->car_audio_stream =
7712 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7713 if (out->car_audio_stream < 0) {
7714 ALOGE("%s: invalid car audio stream %x",
7715 __func__, out->car_audio_stream);
7716 ret = -EINVAL;
7717 goto error_open;
7718 }
Derek Chen5f67a942020-02-24 23:08:13 -08007719 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007720 }
7721
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007722 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007723 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007724 if (!voice_extn_is_compress_voip_supported()) {
7725 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7726 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007727 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7728 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007729 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7730 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007731 out->volume_l = INVALID_OUT_VOLUME;
7732 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007733
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007734 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007735 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007736 uint32_t channel_count =
7737 audio_channel_count_from_out_mask(out->channel_mask);
7738 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7739 out->sample_rate, out->format,
7740 channel_count, false);
7741 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7742 if (frame_size != 0)
7743 out->config.period_size = buffer_size / frame_size;
7744 else
7745 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007746 }
7747 } else {
7748 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7749 voice_extn_compress_voip_is_active(out->dev)) &&
7750 (voice_extn_compress_voip_is_config_supported(config))) {
7751 ret = voice_extn_compress_voip_open_output_stream(out);
7752 if (ret != 0) {
7753 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7754 __func__, ret);
7755 goto error_open;
7756 }
Sujin Panicker19027262019-09-16 18:28:06 +05307757 } else {
7758 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7759 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007760 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007761 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007762 } else if (audio_is_linear_pcm(out->format) &&
7763 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7764 out->channel_mask = config->channel_mask;
7765 out->sample_rate = config->sample_rate;
7766 out->format = config->format;
7767 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7768 // does this change?
7769 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7770 out->config.rate = config->sample_rate;
7771 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7772 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7773 audio_bytes_per_sample(config->format));
7774 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007775 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307776 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307777 pthread_mutex_lock(&adev->lock);
7778 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7779 pthread_mutex_unlock(&adev->lock);
7780
7781 // reject offload during card offline to allow
7782 // fallback to s/w paths
7783 if (offline) {
7784 ret = -ENODEV;
7785 goto error_open;
7786 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007787
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007788 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7789 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7790 ALOGE("%s: Unsupported Offload information", __func__);
7791 ret = -EINVAL;
7792 goto error_open;
7793 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007794
Atul Khare3fa6e542017-08-09 00:56:17 +05307795 if (config->offload_info.format == 0)
7796 config->offload_info.format = config->format;
7797 if (config->offload_info.sample_rate == 0)
7798 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007799
Mingming Yin90310102013-11-13 16:57:00 -08007800 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307801 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007802 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007803 ret = -EINVAL;
7804 goto error_open;
7805 }
7806
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007807 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7808 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7809 (audio_extn_passthru_is_passthrough_stream(out)) &&
7810 !((config->sample_rate == 48000) ||
7811 (config->sample_rate == 96000) ||
7812 (config->sample_rate == 192000))) {
7813 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7814 __func__, config->sample_rate, config->offload_info.format);
7815 ret = -EINVAL;
7816 goto error_open;
7817 }
7818
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007819 out->compr_config.codec = (struct snd_codec *)
7820 calloc(1, sizeof(struct snd_codec));
7821
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007822 if (!out->compr_config.codec) {
7823 ret = -ENOMEM;
7824 goto error_open;
7825 }
7826
Dhananjay Kumarac341582017-02-23 23:42:25 +05307827 out->stream.pause = out_pause;
7828 out->stream.resume = out_resume;
7829 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307830 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307831 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007832 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307833 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007834 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307835 } else {
7836 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7837 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007838 }
vivek mehta446c3962015-09-14 10:57:35 -07007839
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307840 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7841 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007842#ifdef AUDIO_GKI_ENABLED
7843 /* out->compr_config.codec->reserved[1] is for flags */
7844 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7845#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307846 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007847#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307848 }
7849
vivek mehta446c3962015-09-14 10:57:35 -07007850 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007851 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007852 config->format == 0 && config->sample_rate == 0 &&
7853 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007854 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007855 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7856 } else {
7857 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7858 ret = -EEXIST;
7859 goto error_open;
7860 }
vivek mehta446c3962015-09-14 10:57:35 -07007861 }
7862
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007863 if (config->offload_info.channel_mask)
7864 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007865 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007866 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007867 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007868 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307869 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007870 ret = -EINVAL;
7871 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007872 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007873
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007874 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007875 out->sample_rate = config->offload_info.sample_rate;
7876
Mingming Yin3ee55c62014-08-04 14:23:35 -07007877 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007878
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307879 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307880 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307881 audio_extn_dolby_send_ddp_endp_params(adev);
7882 audio_extn_dolby_set_dmid(adev);
7883 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007884
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007885 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007886 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007887 out->compr_config.codec->bit_rate =
7888 config->offload_info.bit_rate;
7889 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307890 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007891 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307892 /* Update bit width only for non passthrough usecases.
7893 * For passthrough usecases, the output will always be opened @16 bit
7894 */
7895 if (!audio_extn_passthru_is_passthrough_stream(out))
7896 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307897
7898 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007899#ifdef AUDIO_GKI_ENABLED
7900 /* out->compr_config.codec->reserved[1] is for flags */
7901 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7902 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7903#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307904 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7905 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007906#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307907
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007908 /*TODO: Do we need to change it for passthrough */
7909 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007910
Manish Dewangana6fc5442015-08-24 20:30:31 +05307911 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7912 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307913 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307914 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307915 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7916 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307917
7918 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7919 AUDIO_FORMAT_PCM) {
7920
7921 /*Based on platform support, configure appropriate alsa format for corresponding
7922 *hal input format.
7923 */
7924 out->compr_config.codec->format = hal_format_to_alsa(
7925 config->offload_info.format);
7926
Ashish Jain83a6cc22016-06-28 14:34:17 +05307927 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307928 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307929 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307930
Dhananjay Kumarac341582017-02-23 23:42:25 +05307931 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307932 *hal input format and alsa format might differ based on platform support.
7933 */
7934 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307935 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307936
7937 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7938
Deeraj Soman93155a62019-09-30 19:00:37 +05307939 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7940 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7941 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7942 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7943 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307944
Ashish Jainf1eaa582016-05-23 20:54:24 +05307945 /* Check if alsa session is configured with the same format as HAL input format,
7946 * if not then derive correct fragment size needed to accomodate the
7947 * conversion of HAL input format to alsa format.
7948 */
7949 audio_extn_utils_update_direct_pcm_fragment_size(out);
7950
7951 /*if hal input and output fragment size is different this indicates HAL input format is
7952 *not same as the alsa format
7953 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307954 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307955 /*Allocate a buffer to convert input data to the alsa configured format.
7956 *size of convert buffer is equal to the size required to hold one fragment size
7957 *worth of pcm data, this is because flinger does not write more than fragment_size
7958 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307959 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7960 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307961 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7962 ret = -ENOMEM;
7963 goto error_open;
7964 }
7965 }
7966 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7967 out->compr_config.fragment_size =
7968 audio_extn_passthru_get_buffer_size(&config->offload_info);
7969 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7970 } else {
7971 out->compr_config.fragment_size =
7972 platform_get_compress_offload_buffer_size(&config->offload_info);
7973 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7974 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007975
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307976 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7977 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7978 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007979 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307980 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007981
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307982 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7983 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7984 }
7985
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007986 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7987 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007988
Manish Dewangan69426c82017-01-30 17:35:36 +05307989 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7990 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7991 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7992 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7993 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7994 } else {
7995 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7996 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007997
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307998 memset(&out->channel_map_param, 0,
7999 sizeof(struct audio_out_channel_map_param));
8000
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008001 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308002 out->send_next_track_params = false;
8003 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008004 out->offload_state = OFFLOAD_STATE_IDLE;
8005 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008006 out->writeAt.tv_sec = 0;
8007 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008008
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008009 audio_extn_dts_create_state_notifier_node(out->usecase);
8010
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008011 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8012 __func__, config->offload_info.version,
8013 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308014
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308015 /* Check if DSD audio format is supported in codec
8016 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308017 */
8018
8019 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308020 (!platform_check_codec_dsd_support(adev->platform) ||
8021 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308022 ret = -EINVAL;
8023 goto error_open;
8024 }
8025
Ashish Jain5106d362016-05-11 19:23:33 +05308026 /* Disable gapless if any of the following is true
8027 * passthrough playback
8028 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308029 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308030 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308031 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308032 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008033 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308034 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308035 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308036 check_and_set_gapless_mode(adev, false);
8037 } else
8038 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008039
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308040 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008041 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8042 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308043 if (config->format == AUDIO_FORMAT_DSD) {
8044 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008045#ifdef AUDIO_GKI_ENABLED
8046 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8047 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8048#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308049 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008050#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308051 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008052
8053 create_offload_callback_thread(out);
8054
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008055 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008056 switch (config->sample_rate) {
8057 case 0:
8058 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8059 break;
8060 case 8000:
8061 case 16000:
8062 case 48000:
8063 out->sample_rate = config->sample_rate;
8064 break;
8065 default:
8066 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8067 config->sample_rate);
8068 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8069 ret = -EINVAL;
8070 goto error_open;
8071 }
8072 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8073 switch (config->channel_mask) {
8074 case AUDIO_CHANNEL_NONE:
8075 case AUDIO_CHANNEL_OUT_STEREO:
8076 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8077 break;
8078 default:
8079 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8080 config->channel_mask);
8081 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8082 ret = -EINVAL;
8083 goto error_open;
8084 }
8085 switch (config->format) {
8086 case AUDIO_FORMAT_DEFAULT:
8087 case AUDIO_FORMAT_PCM_16_BIT:
8088 out->format = AUDIO_FORMAT_PCM_16_BIT;
8089 break;
8090 default:
8091 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8092 config->format);
8093 config->format = AUDIO_FORMAT_PCM_16_BIT;
8094 ret = -EINVAL;
8095 goto error_open;
8096 }
8097
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308098 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008099 if (ret != 0) {
8100 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008101 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008102 goto error_open;
8103 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008104 } else if (is_single_device_type_equal(&out->device_list,
8105 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008106 switch (config->sample_rate) {
8107 case 0:
8108 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8109 break;
8110 case 8000:
8111 case 16000:
8112 case 48000:
8113 out->sample_rate = config->sample_rate;
8114 break;
8115 default:
8116 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8117 config->sample_rate);
8118 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8119 ret = -EINVAL;
8120 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008121 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008122 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8123 switch (config->channel_mask) {
8124 case AUDIO_CHANNEL_NONE:
8125 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8126 break;
8127 case AUDIO_CHANNEL_OUT_STEREO:
8128 out->channel_mask = config->channel_mask;
8129 break;
8130 default:
8131 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8132 config->channel_mask);
8133 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8134 ret = -EINVAL;
8135 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008136 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008137 switch (config->format) {
8138 case AUDIO_FORMAT_DEFAULT:
8139 out->format = AUDIO_FORMAT_PCM_16_BIT;
8140 break;
8141 case AUDIO_FORMAT_PCM_16_BIT:
8142 out->format = config->format;
8143 break;
8144 default:
8145 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8146 config->format);
8147 config->format = AUDIO_FORMAT_PCM_16_BIT;
8148 ret = -EINVAL;
8149 break;
8150 }
8151 if (ret != 0)
8152 goto error_open;
8153
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008154 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8155 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008156 out->config.rate = out->sample_rate;
8157 out->config.channels =
8158 audio_channel_count_from_out_mask(out->channel_mask);
8159 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008160 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008161 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308162 unsigned int channels = 0;
8163 /*Update config params to default if not set by the caller*/
8164 if (config->sample_rate == 0)
8165 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8166 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8167 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8168 if (config->format == AUDIO_FORMAT_DEFAULT)
8169 config->format = AUDIO_FORMAT_PCM_16_BIT;
8170
8171 channels = audio_channel_count_from_out_mask(out->channel_mask);
8172
Varun Balaraje49253e2017-07-06 19:48:56 +05308173 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8174 out->usecase = get_interactive_usecase(adev);
8175 out->config = pcm_config_low_latency;
8176 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308177 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008178 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8179 out->flags);
8180 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008181 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8182 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8183 out->config = pcm_config_mmap_playback;
8184 out->stream.start = out_start;
8185 out->stream.stop = out_stop;
8186 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8187 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308188 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8189 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008190 out->hal_output_suspend_supported =
8191 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8192 out->dynamic_pm_qos_config_supported =
8193 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8194 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008195 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8196 } else {
8197 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8198 //the mixer path will be a string similar to "low-latency-playback resume"
8199 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8200 strlcat(out->pm_qos_mixer_path,
8201 " resume", MAX_MIXER_PATH_LEN);
8202 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8203 out->pm_qos_mixer_path);
8204 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308205 out->config = pcm_config_low_latency;
8206 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8207 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8208 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308209 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8210 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8211 if (out->config.period_size <= 0) {
8212 ALOGE("Invalid configuration period size is not valid");
8213 ret = -EINVAL;
8214 goto error_open;
8215 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008216 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8217 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8218 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008219 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8220 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8221 out->config = pcm_config_haptics_audio;
8222 if (force_haptic_path)
8223 adev->haptics_config = pcm_config_haptics_audio;
8224 else
8225 adev->haptics_config = pcm_config_haptics;
8226
Meng Wangd08ce322020-04-02 08:59:20 +08008227 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008228 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8229
8230 if (force_haptic_path) {
8231 out->config.channels = 1;
8232 adev->haptics_config.channels = 1;
8233 } else
8234 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 -08008235 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008236 ret = audio_extn_auto_hal_open_output_stream(out);
8237 if (ret) {
8238 ALOGE("%s: Failed to open output stream for bus device", __func__);
8239 ret = -EINVAL;
8240 goto error_open;
8241 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308242 } else {
8243 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008244 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8245 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308246 }
8247 out->hal_ip_format = format = out->format;
8248 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8249 out->hal_op_format = pcm_format_to_hal(out->config.format);
8250 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8251 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008252 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308253 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308254 if (out->hal_ip_format != out->hal_op_format) {
8255 uint32_t buffer_size = out->config.period_size *
8256 format_to_bitwidth_table[out->hal_op_format] *
8257 out->config.channels;
8258 out->convert_buffer = calloc(1, buffer_size);
8259 if (out->convert_buffer == NULL){
8260 ALOGE("Allocation failed for convert buffer for size %d",
8261 out->compr_config.fragment_size);
8262 ret = -ENOMEM;
8263 goto error_open;
8264 }
8265 ALOGD("Convert buffer allocated of size %d", buffer_size);
8266 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008267 }
8268
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008269 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8270 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308271
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008272 /* TODO remove this hardcoding and check why width is zero*/
8273 if (out->bit_width == 0)
8274 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308275 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008276 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008277 &out->device_list, out->flags,
8278 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308279 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308280 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008281 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008282 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8283 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008284 if(adev->primary_output == NULL)
8285 adev->primary_output = out;
8286 else {
8287 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008288 ret = -EEXIST;
8289 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008290 }
8291 }
8292
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008293 /* Check if this usecase is already existing */
8294 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008295 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8296 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008297 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008298 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008299 ret = -EEXIST;
8300 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008301 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008302
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008303 pthread_mutex_unlock(&adev->lock);
8304
8305 out->stream.common.get_sample_rate = out_get_sample_rate;
8306 out->stream.common.set_sample_rate = out_set_sample_rate;
8307 out->stream.common.get_buffer_size = out_get_buffer_size;
8308 out->stream.common.get_channels = out_get_channels;
8309 out->stream.common.get_format = out_get_format;
8310 out->stream.common.set_format = out_set_format;
8311 out->stream.common.standby = out_standby;
8312 out->stream.common.dump = out_dump;
8313 out->stream.common.set_parameters = out_set_parameters;
8314 out->stream.common.get_parameters = out_get_parameters;
8315 out->stream.common.add_audio_effect = out_add_audio_effect;
8316 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8317 out->stream.get_latency = out_get_latency;
8318 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008319#ifdef NO_AUDIO_OUT
8320 out->stream.write = out_write_for_no_output;
8321#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008322 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008323#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008324 out->stream.get_render_position = out_get_render_position;
8325 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008326 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008327
Haynes Mathew George16081042017-05-31 17:16:49 -07008328 if (out->realtime)
8329 out->af_period_multiplier = af_period_multiplier;
8330 else
8331 out->af_period_multiplier = 1;
8332
Andy Hunga1f48fa2019-07-01 18:14:53 -07008333 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008335 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008336 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008337 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008338
8339 config->format = out->stream.common.get_format(&out->stream.common);
8340 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8341 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308342 register_format(out->format, out->supported_formats);
8343 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8344 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008345
Aalique Grahame22e49102018-12-18 14:23:57 -08008346 out->error_log = error_log_create(
8347 ERROR_LOG_ENTRIES,
8348 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8349
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308350 /*
8351 By locking output stream before registering, we allow the callback
8352 to update stream's state only after stream's initial state is set to
8353 adev state.
8354 */
8355 lock_output_stream(out);
8356 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8357 pthread_mutex_lock(&adev->lock);
8358 out->card_status = adev->card_status;
8359 pthread_mutex_unlock(&adev->lock);
8360 pthread_mutex_unlock(&out->lock);
8361
Aalique Grahame22e49102018-12-18 14:23:57 -08008362 stream_app_type_cfg_init(&out->app_type_cfg);
8363
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008364 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308365 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008366 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008367
8368 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8369 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8370 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008371 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308372 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008373 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008374 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308375 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8376 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008377 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8378 out->usecase, PCM_PLAYBACK);
8379 hdlr_stream_cfg.flags = out->flags;
8380 hdlr_stream_cfg.type = PCM_PLAYBACK;
8381 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8382 &hdlr_stream_cfg);
8383 if (ret) {
8384 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8385 out->adsp_hdlr_stream_handle = NULL;
8386 }
8387 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308388 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8389 is_direct_passthough, false);
8390 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8391 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008392 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008393 if (ret < 0) {
8394 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8395 out->ip_hdlr_handle = NULL;
8396 }
8397 }
Derek Chenf939fb72018-11-13 13:34:41 -08008398
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008399 ret = io_streams_map_insert(adev, &out->stream.common,
8400 out->handle, AUDIO_PATCH_HANDLE_NONE);
8401 if (ret != 0)
8402 goto error_open;
8403
Derek Chenf939fb72018-11-13 13:34:41 -08008404 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8405 calloc(1, sizeof(streams_output_ctxt_t));
8406 if (out_ctxt == NULL) {
8407 ALOGE("%s fail to allocate output ctxt", __func__);
8408 ret = -ENOMEM;
8409 goto error_open;
8410 }
8411 out_ctxt->output = out;
8412
8413 pthread_mutex_lock(&adev->lock);
8414 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8415 pthread_mutex_unlock(&adev->lock);
8416
Eric Laurent994a6932013-07-17 11:51:42 -07008417 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008418 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008419
8420error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308421 if (out->convert_buffer)
8422 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008423 free(out);
8424 *stream_out = NULL;
8425 ALOGD("%s: exit: ret %d", __func__, ret);
8426 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008427}
8428
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308429void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008430 struct audio_stream_out *stream)
8431{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008432 struct stream_out *out = (struct stream_out *)stream;
8433 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008434 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008435
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008436 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308437
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008438 io_streams_map_remove(adev, out->handle);
8439
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308440 // must deregister from sndmonitor first to prevent races
8441 // between the callback and close_stream
8442 audio_extn_snd_mon_unregister_listener(out);
8443
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008444 /* close adsp hdrl session before standby */
8445 if (out->adsp_hdlr_stream_handle) {
8446 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8447 if (ret)
8448 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8449 out->adsp_hdlr_stream_handle = NULL;
8450 }
8451
Manish Dewangan21a850a2017-08-14 12:03:55 +05308452 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008453 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8454 out->ip_hdlr_handle = NULL;
8455 }
8456
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008457 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308458 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008459 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308460 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308461 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008462 if(ret != 0)
8463 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8464 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008465 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008466 out_standby(&stream->common);
8467
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008468 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008469 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008470 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008471 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008472 if (out->compr_config.codec != NULL)
8473 free(out->compr_config.codec);
8474 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008475
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308476 out->a2dp_compress_mute = false;
8477
Varun Balaraje49253e2017-07-06 19:48:56 +05308478 if (is_interactive_usecase(out->usecase))
8479 free_interactive_usecase(adev, out->usecase);
8480
Ashish Jain83a6cc22016-06-28 14:34:17 +05308481 if (out->convert_buffer != NULL) {
8482 free(out->convert_buffer);
8483 out->convert_buffer = NULL;
8484 }
8485
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008486 if (adev->voice_tx_output == out)
8487 adev->voice_tx_output = NULL;
8488
Aalique Grahame22e49102018-12-18 14:23:57 -08008489 error_log_destroy(out->error_log);
8490 out->error_log = NULL;
8491
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308492 if (adev->primary_output == out)
8493 adev->primary_output = NULL;
8494
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008495 pthread_cond_destroy(&out->cond);
8496 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008497
8498 pthread_mutex_lock(&adev->lock);
8499 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8500 if (out_ctxt != NULL) {
8501 list_remove(&out_ctxt->list);
8502 free(out_ctxt);
8503 } else {
8504 ALOGW("%s, output stream already closed", __func__);
8505 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008506 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008507 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008508 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008509}
8510
8511static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8512{
8513 struct audio_device *adev = (struct audio_device *)dev;
8514 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008515 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008516 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008517 int ret;
8518 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008519 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008520 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008521 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008522
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008523 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008524 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008525
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308526 if (!parms)
8527 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308528
Derek Chen6f293672019-04-01 01:40:24 -07008529 /* notify adev and input/output streams on the snd card status */
8530 adev_snd_mon_cb((void *)adev, parms);
8531
8532 list_for_each(node, &adev->active_outputs_list) {
8533 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8534 streams_output_ctxt_t,
8535 list);
8536 out_snd_mon_cb((void *)out_ctxt->output, parms);
8537 }
8538
8539 list_for_each(node, &adev->active_inputs_list) {
8540 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8541 streams_input_ctxt_t,
8542 list);
8543 in_snd_mon_cb((void *)in_ctxt->input, parms);
8544 }
8545
Zhou Songd6d71752019-05-21 18:08:51 +08008546 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308547 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8548 if (ret >= 0) {
8549 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008550 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308551 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008552 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308553 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008554 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008555 }
8556 }
8557
8558 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8559 if (ret>=0) {
8560 if (!strncmp(value, "false", 5) &&
8561 audio_extn_a2dp_source_is_suspended()) {
8562 struct audio_usecase *usecase;
8563 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008564 list_for_each(node, &adev->usecase_list) {
8565 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008566 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008567 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008568 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008569 reassign_device_list(&usecase->stream.in->device_list,
8570 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008571 select_devices(adev, usecase->id);
8572 }
Zhou Songd6d71752019-05-21 18:08:51 +08008573 }
8574 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308575 }
8576
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008577 status = voice_set_parameters(adev, parms);
8578 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008579 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008580
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008581 status = platform_set_parameters(adev->platform, parms);
8582 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008583 goto done;
8584
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008585 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8586 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008587 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008588 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8589 adev->bluetooth_nrec = true;
8590 else
8591 adev->bluetooth_nrec = false;
8592 }
8593
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008594 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8595 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008596 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8597 adev->screen_off = false;
8598 else
8599 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008600 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008601 }
8602
Eric Laurent4b084132018-10-19 17:33:43 -07008603 ret = str_parms_get_int(parms, "rotation", &val);
8604 if (ret >= 0) {
8605 bool reverse_speakers = false;
8606 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8607 switch (val) {
8608 // FIXME: note that the code below assumes that the speakers are in the correct placement
8609 // relative to the user when the device is rotated 90deg from its default rotation. This
8610 // assumption is device-specific, not platform-specific like this code.
8611 case 270:
8612 reverse_speakers = true;
8613 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8614 break;
8615 case 0:
8616 case 180:
8617 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8618 break;
8619 case 90:
8620 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8621 break;
8622 default:
8623 ALOGE("%s: unexpected rotation of %d", __func__, val);
8624 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008625 }
Eric Laurent4b084132018-10-19 17:33:43 -07008626 if (status == 0) {
8627 // check and set swap
8628 // - check if orientation changed and speaker active
8629 // - set rotation and cache the rotation value
8630 adev->camera_orientation =
8631 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8632 if (!audio_extn_is_maxx_audio_enabled())
8633 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8634 }
8635 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008636
Mingming Yin514a8bc2014-07-29 15:22:21 -07008637 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8638 if (ret >= 0) {
8639 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8640 adev->bt_wb_speech_enabled = true;
8641 else
8642 adev->bt_wb_speech_enabled = false;
8643 }
8644
Zhou Song12c29502019-03-16 10:37:18 +08008645 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8646 if (ret >= 0) {
8647 val = atoi(value);
8648 adev->swb_speech_mode = val;
8649 }
8650
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008651 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8652 if (ret >= 0) {
8653 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308654 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008655 if (audio_is_output_device(val) &&
8656 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008657 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008658 platform_get_controller_stream_from_params(parms, &controller, &stream);
8659 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8660 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008661 if (ret < 0) {
8662 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308663 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008664 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008665 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308666 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008667 /*
8668 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8669 * Per AudioPolicyManager, USB device is higher priority than WFD.
8670 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8671 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8672 * starting voice call on USB
8673 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008674 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308675 if (ret >= 0)
8676 audio_extn_usb_add_device(device, atoi(value));
8677
Zhou Song6f862822017-11-06 17:27:57 +08008678 if (!audio_extn_usb_is_tunnel_supported()) {
8679 ALOGV("detected USB connect .. disable proxy");
8680 adev->allow_afe_proxy_usage = false;
8681 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008682 }
8683 }
8684
8685 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8686 if (ret >= 0) {
8687 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308688 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008689 /*
8690 * The HDMI / Displayport disconnect handling has been moved to
8691 * audio extension to ensure that its parameters are not
8692 * invalidated prior to updating sysfs of the disconnect event
8693 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8694 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308695 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008696 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308697 if (ret >= 0)
8698 audio_extn_usb_remove_device(device, atoi(value));
8699
Zhou Song6f862822017-11-06 17:27:57 +08008700 if (!audio_extn_usb_is_tunnel_supported()) {
8701 ALOGV("detected USB disconnect .. enable proxy");
8702 adev->allow_afe_proxy_usage = true;
8703 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008704 }
8705 }
8706
Aalique Grahame22e49102018-12-18 14:23:57 -08008707 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008708 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008709
8710 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008711 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308712 struct audio_usecase *usecase;
8713 struct listnode *node;
8714 list_for_each(node, &adev->usecase_list) {
8715 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308716 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008717 is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308718 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008719 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308720 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008721 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308722 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308723 ALOGD("Switching to speaker and muting the stream before select_devices");
8724 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308725 //force device switch to re configure encoder
8726 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308727 ALOGD("Unmuting the stream after select_devices");
8728 usecase->stream.out->a2dp_compress_mute = false;
8729 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 +05308730 audio_extn_a2dp_set_handoff_mode(false);
8731 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308732 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308733 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8734 usecase->stream.out->a2dp_compress_mute) {
8735 pthread_mutex_unlock(&adev->lock);
8736 lock_output_stream(usecase->stream.out);
8737 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008738 reassign_device_list(&usecase->stream.out->device_list,
8739 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308740 check_a2dp_restore_l(adev, usecase->stream.out, true);
8741 pthread_mutex_unlock(&usecase->stream.out->lock);
8742 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308743 }
8744 }
8745 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008746
8747 //handle vr audio setparam
8748 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8749 value, sizeof(value));
8750 if (ret >= 0) {
8751 ALOGI("Setting vr mode to be %s", value);
8752 if (!strncmp(value, "true", 4)) {
8753 adev->vr_audio_mode_enabled = true;
8754 ALOGI("Setting vr mode to true");
8755 } else if (!strncmp(value, "false", 5)) {
8756 adev->vr_audio_mode_enabled = false;
8757 ALOGI("Setting vr mode to false");
8758 } else {
8759 ALOGI("wrong vr mode set");
8760 }
8761 }
8762
Eric Laurent4b084132018-10-19 17:33:43 -07008763 //FIXME: to be replaced by proper video capture properties API
8764 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8765 if (ret >= 0) {
8766 int camera_facing = CAMERA_FACING_BACK;
8767 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8768 camera_facing = CAMERA_FACING_FRONT;
8769 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8770 camera_facing = CAMERA_FACING_BACK;
8771 else {
8772 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8773 goto done;
8774 }
8775 adev->camera_orientation =
8776 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8777 struct audio_usecase *usecase;
8778 struct listnode *node;
8779 list_for_each(node, &adev->usecase_list) {
8780 usecase = node_to_item(node, struct audio_usecase, list);
8781 struct stream_in *in = usecase->stream.in;
8782 if (usecase->type == PCM_CAPTURE && in != NULL &&
8783 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8784 select_devices(adev, in->usecase);
8785 }
8786 }
8787 }
8788
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308789 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008790done:
8791 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008792 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308793error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008794 ALOGV("%s: exit with code(%d)", __func__, status);
8795 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008796}
8797
8798static char* adev_get_parameters(const struct audio_hw_device *dev,
8799 const char *keys)
8800{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308801 ALOGD("%s:%s", __func__, keys);
8802
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008803 struct audio_device *adev = (struct audio_device *)dev;
8804 struct str_parms *reply = str_parms_create();
8805 struct str_parms *query = str_parms_create_str(keys);
8806 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308807 char value[256] = {0};
8808 int ret = 0;
8809
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008810 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008811 if (reply) {
8812 str_parms_destroy(reply);
8813 }
8814 if (query) {
8815 str_parms_destroy(query);
8816 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008817 ALOGE("adev_get_parameters: failed to create query or reply");
8818 return NULL;
8819 }
8820
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008821 //handle vr audio getparam
8822
8823 ret = str_parms_get_str(query,
8824 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8825 value, sizeof(value));
8826
8827 if (ret >= 0) {
8828 bool vr_audio_enabled = false;
8829 pthread_mutex_lock(&adev->lock);
8830 vr_audio_enabled = adev->vr_audio_mode_enabled;
8831 pthread_mutex_unlock(&adev->lock);
8832
8833 ALOGI("getting vr mode to %d", vr_audio_enabled);
8834
8835 if (vr_audio_enabled) {
8836 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8837 "true");
8838 goto exit;
8839 } else {
8840 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8841 "false");
8842 goto exit;
8843 }
8844 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008845
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008846 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008847 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008848 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008849 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008850 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08008851 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308852 pthread_mutex_unlock(&adev->lock);
8853
Naresh Tannirud7205b62014-06-20 02:54:48 +05308854exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008855 str = str_parms_to_str(reply);
8856 str_parms_destroy(query);
8857 str_parms_destroy(reply);
8858
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308859 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008860 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008861}
8862
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008863static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008864{
8865 return 0;
8866}
8867
8868static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8869{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008870 int ret;
8871 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008872
8873 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8874
Haynes Mathew George5191a852013-09-11 14:19:36 -07008875 pthread_mutex_lock(&adev->lock);
8876 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008877 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008878 pthread_mutex_unlock(&adev->lock);
8879 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008880}
8881
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008882static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8883 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008884{
8885 return -ENOSYS;
8886}
8887
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008888static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8889 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008890{
8891 return -ENOSYS;
8892}
8893
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008894static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8895 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008896{
8897 return -ENOSYS;
8898}
8899
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008900static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8901 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008902{
8903 return -ENOSYS;
8904}
8905
8906static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8907{
8908 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008909 struct listnode *node;
8910 struct audio_usecase *usecase = NULL;
8911 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008913 pthread_mutex_lock(&adev->lock);
8914 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05308915 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
8916 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008917 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05308918 if( mode == AUDIO_MODE_CALL_SCREEN ){
8919 adev->current_call_output = adev->primary_output;
8920 voice_start_call(adev);
8921 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008922 (mode == AUDIO_MODE_NORMAL ||
8923 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008924 list_for_each(node, &adev->usecase_list) {
8925 usecase = node_to_item(node, struct audio_usecase, list);
8926 if (usecase->type == VOICE_CALL)
8927 break;
8928 }
8929 if (usecase &&
8930 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8931 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8932 true);
8933 if (ret != 0) {
8934 /* default service interval was successfully updated,
8935 reopen USB backend with new service interval */
8936 check_usecases_codec_backend(adev,
8937 usecase,
8938 usecase->out_snd_device);
8939 }
8940 }
8941
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008942 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008943 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008944 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008945 // restore device for other active usecases after stop call
8946 list_for_each(node, &adev->usecase_list) {
8947 usecase = node_to_item(node, struct audio_usecase, list);
8948 select_devices(adev, usecase->id);
8949 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008950 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008951 }
8952 pthread_mutex_unlock(&adev->lock);
8953 return 0;
8954}
8955
8956static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8957{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008958 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008959 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008960
8961 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008962 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008963 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008964
Derek Chend2530072014-11-24 12:39:14 -08008965 if (adev->ext_hw_plugin)
8966 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008967
8968 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008969 pthread_mutex_unlock(&adev->lock);
8970
8971 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008972}
8973
8974static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8975{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008976 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008977 return 0;
8978}
8979
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008980static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008981 const struct audio_config *config)
8982{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008983 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008984
Aalique Grahame22e49102018-12-18 14:23:57 -08008985 /* Don't know if USB HIFI in this context so use true to be conservative */
8986 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8987 true /*is_usb_hifi */) != 0)
8988 return 0;
8989
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008990 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8991 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008992}
8993
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008994static bool adev_input_allow_hifi_record(struct audio_device *adev,
8995 audio_devices_t devices,
8996 audio_input_flags_t flags,
8997 audio_source_t source) {
8998 const bool allowed = true;
8999
9000 if (!audio_is_usb_in_device(devices))
9001 return !allowed;
9002
9003 switch (flags) {
9004 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009005 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009006 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9007 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009008 default:
9009 return !allowed;
9010 }
9011
9012 switch (source) {
9013 case AUDIO_SOURCE_DEFAULT:
9014 case AUDIO_SOURCE_MIC:
9015 case AUDIO_SOURCE_UNPROCESSED:
9016 break;
9017 default:
9018 return !allowed;
9019 }
9020
9021 switch (adev->mode) {
9022 case 0:
9023 break;
9024 default:
9025 return !allowed;
9026 }
9027
9028 return allowed;
9029}
9030
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009031static int adev_update_voice_comm_input_stream(struct stream_in *in,
9032 struct audio_config *config)
9033{
9034 bool valid_rate = (config->sample_rate == 8000 ||
9035 config->sample_rate == 16000 ||
9036 config->sample_rate == 32000 ||
9037 config->sample_rate == 48000);
9038 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9039
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009040 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009041 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009042 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9043 in->config = default_pcm_config_voip_copp;
9044 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9045 DEFAULT_VOIP_BUF_DURATION_MS,
9046 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009047 } else {
9048 ALOGW("%s No valid input in voip, use defaults"
9049 "sample rate %u, channel mask 0x%X",
9050 __func__, config->sample_rate, in->channel_mask);
9051 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009052 in->config.rate = config->sample_rate;
9053 in->sample_rate = config->sample_rate;
9054 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009055 //XXX needed for voice_extn_compress_voip_open_input_stream
9056 in->config.rate = config->sample_rate;
9057 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309058 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009059 voice_extn_compress_voip_is_active(in->dev)) &&
9060 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9061 valid_rate && valid_ch) {
9062 voice_extn_compress_voip_open_input_stream(in);
9063 // update rate entries to match config from AF
9064 in->config.rate = config->sample_rate;
9065 in->sample_rate = config->sample_rate;
9066 } else {
9067 ALOGW("%s compress voip not active, use defaults", __func__);
9068 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009069 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009070 return 0;
9071}
9072
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009073static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009074 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009075 audio_devices_t devices,
9076 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009077 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309078 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009079 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009080 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009081{
9082 struct audio_device *adev = (struct audio_device *)dev;
9083 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009084 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009085 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009086 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309087 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009088 bool is_usb_dev = audio_is_usb_in_device(devices);
9089 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9090 devices,
9091 flags,
9092 source);
Andy Hung94320602018-10-29 18:31:12 -07009093 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9094 " sample_rate %u, channel_mask %#x, format %#x",
9095 __func__, flags, is_usb_dev, may_use_hifi_record,
9096 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309097
kunleizdff872d2018-08-20 14:40:33 +08009098 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009099 is_usb_dev = false;
9100 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9101 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9102 __func__, devices);
9103 }
9104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009105 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009106
9107 if (!(is_usb_dev && may_use_hifi_record)) {
9108 if (config->sample_rate == 0)
9109 config->sample_rate = 48000;
9110 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9111 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9112 if (config->format == AUDIO_FORMAT_DEFAULT)
9113 config->format = AUDIO_FORMAT_PCM_16_BIT;
9114
9115 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9116
Aalique Grahame22e49102018-12-18 14:23:57 -08009117 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9118 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009119 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309120 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009121
Rahul Sharma99770982019-03-06 17:05:26 +05309122 pthread_mutex_lock(&adev->lock);
9123 if (in_get_stream(adev, handle) != NULL) {
9124 ALOGW("%s, input stream already opened", __func__);
9125 ret = -EEXIST;
9126 }
9127 pthread_mutex_unlock(&adev->lock);
9128 if (ret)
9129 return ret;
9130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009131 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009132
9133 if (!in) {
9134 ALOGE("failed to allocate input stream");
9135 return -ENOMEM;
9136 }
9137
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309138 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309139 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9140 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009141 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009142 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009143
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009144 in->stream.common.get_sample_rate = in_get_sample_rate;
9145 in->stream.common.set_sample_rate = in_set_sample_rate;
9146 in->stream.common.get_buffer_size = in_get_buffer_size;
9147 in->stream.common.get_channels = in_get_channels;
9148 in->stream.common.get_format = in_get_format;
9149 in->stream.common.set_format = in_set_format;
9150 in->stream.common.standby = in_standby;
9151 in->stream.common.dump = in_dump;
9152 in->stream.common.set_parameters = in_set_parameters;
9153 in->stream.common.get_parameters = in_get_parameters;
9154 in->stream.common.add_audio_effect = in_add_audio_effect;
9155 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9156 in->stream.set_gain = in_set_gain;
9157 in->stream.read = in_read;
9158 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009159 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309160 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009161 in->stream.set_microphone_direction = in_set_microphone_direction;
9162 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009163 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009164
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009165 list_init(&in->device_list);
9166 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009167 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009168 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009169 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009170 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009171 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009172 in->bit_width = 16;
9173 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009174 in->direction = MIC_DIRECTION_UNSPECIFIED;
9175 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009176 list_init(&in->aec_list);
9177 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009178 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009179
Andy Hung94320602018-10-29 18:31:12 -07009180 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009181 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9182 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9183 /* Force channel config requested to mono if incall
9184 record is being requested for only uplink/downlink */
9185 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9186 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9187 ret = -EINVAL;
9188 goto err_open;
9189 }
9190 }
9191
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009192 if (is_usb_dev && may_use_hifi_record) {
9193 /* HiFi record selects an appropriate format, channel, rate combo
9194 depending on sink capabilities*/
9195 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9196 &config->format,
9197 &in->supported_formats[0],
9198 MAX_SUPPORTED_FORMATS,
9199 &config->channel_mask,
9200 &in->supported_channel_masks[0],
9201 MAX_SUPPORTED_CHANNEL_MASKS,
9202 &config->sample_rate,
9203 &in->supported_sample_rates[0],
9204 MAX_SUPPORTED_SAMPLE_RATES);
9205 if (ret != 0) {
9206 ret = -EINVAL;
9207 goto err_open;
9208 }
9209 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009210 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309211 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309212 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9213 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9214 in->config.format = PCM_FORMAT_S32_LE;
9215 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309216 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9217 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9218 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9219 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9220 bool ret_error = false;
9221 in->bit_width = 24;
9222 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9223 from HAL is 24_packed and 8_24
9224 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9225 24_packed return error indicating supported format is 24_packed
9226 *> In case of any other source requesting 24 bit or float return error
9227 indicating format supported is 16 bit only.
9228
9229 on error flinger will retry with supported format passed
9230 */
9231 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9232 (source != AUDIO_SOURCE_CAMCORDER)) {
9233 config->format = AUDIO_FORMAT_PCM_16_BIT;
9234 if (config->sample_rate > 48000)
9235 config->sample_rate = 48000;
9236 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009237 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9238 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309239 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9240 ret_error = true;
9241 }
9242
9243 if (ret_error) {
9244 ret = -EINVAL;
9245 goto err_open;
9246 }
9247 }
9248
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009249 in->channel_mask = config->channel_mask;
9250 in->format = config->format;
9251
9252 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309253
9254 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9255 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9256 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9257 else {
9258 ret = -EINVAL;
9259 goto err_open;
9260 }
9261 }
9262
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009263 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309264 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9265 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009266 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9267 is_low_latency = true;
9268#if LOW_LATENCY_CAPTURE_USE_CASE
9269 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9270#endif
9271 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009272 if (!in->realtime) {
9273 in->config = pcm_config_audio_capture;
9274 frame_size = audio_stream_in_frame_size(&in->stream);
9275 buffer_size = get_input_buffer_size(config->sample_rate,
9276 config->format,
9277 channel_count,
9278 is_low_latency);
9279 in->config.period_size = buffer_size / frame_size;
9280 in->config.rate = config->sample_rate;
9281 in->af_period_multiplier = 1;
9282 } else {
9283 // period size is left untouched for rt mode playback
9284 in->config = pcm_config_audio_capture_rt;
9285 in->af_period_multiplier = af_period_multiplier;
9286 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009287 }
9288
9289 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9290 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9291 in->realtime = 0;
9292 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9293 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009294 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009295 in->stream.start = in_start;
9296 in->stream.stop = in_stop;
9297 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9298 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009299 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009300 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009301 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9302 in->config = pcm_config_audio_capture;
9303 frame_size = audio_stream_in_frame_size(&in->stream);
9304 buffer_size = get_input_buffer_size(config->sample_rate,
9305 config->format,
9306 channel_count,
9307 false /*is_low_latency*/);
9308 in->config.period_size = buffer_size / frame_size;
9309 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009310 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009311 switch (config->format) {
9312 case AUDIO_FORMAT_PCM_32_BIT:
9313 in->bit_width = 32;
9314 break;
9315 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9316 case AUDIO_FORMAT_PCM_8_24_BIT:
9317 in->bit_width = 24;
9318 break;
9319 default:
9320 in->bit_width = 16;
9321 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009322 } else if (is_single_device_type_equal(&in->device_list,
9323 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9324 is_single_device_type_equal(&in->device_list,
9325 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009326 if (config->sample_rate == 0)
9327 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9328 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9329 config->sample_rate != 8000) {
9330 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9331 ret = -EINVAL;
9332 goto err_open;
9333 }
9334 if (config->format == AUDIO_FORMAT_DEFAULT)
9335 config->format = AUDIO_FORMAT_PCM_16_BIT;
9336 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9337 config->format = AUDIO_FORMAT_PCM_16_BIT;
9338 ret = -EINVAL;
9339 goto err_open;
9340 }
9341
9342 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
9343 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009344 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009345 in->af_period_multiplier = 1;
9346 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9347 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9348 (config->sample_rate == 8000 ||
9349 config->sample_rate == 16000 ||
9350 config->sample_rate == 32000 ||
9351 config->sample_rate == 48000) &&
9352 channel_count == 1) {
9353 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9354 in->config = pcm_config_audio_capture;
9355 frame_size = audio_stream_in_frame_size(&in->stream);
9356 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9357 config->sample_rate,
9358 config->format,
9359 channel_count, false /*is_low_latency*/);
9360 in->config.period_size = buffer_size / frame_size;
9361 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9362 in->config.rate = config->sample_rate;
9363 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009364 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309365 int ret_val;
9366 pthread_mutex_lock(&adev->lock);
9367 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9368 in, config, &channel_mask_updated);
9369 pthread_mutex_unlock(&adev->lock);
9370
9371 if (!ret_val) {
9372 if (channel_mask_updated == true) {
9373 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9374 __func__, config->channel_mask);
9375 ret = -EINVAL;
9376 goto err_open;
9377 }
9378 ALOGD("%s: created multi-channel session succesfully",__func__);
9379 } else if (audio_extn_compr_cap_enabled() &&
9380 audio_extn_compr_cap_format_supported(config->format) &&
9381 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9382 audio_extn_compr_cap_init(in);
9383 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309384 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309385 if (ret)
9386 goto err_open;
9387 } else {
9388 in->config = pcm_config_audio_capture;
9389 in->config.rate = config->sample_rate;
9390 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309391 in->format = config->format;
9392 frame_size = audio_stream_in_frame_size(&in->stream);
9393 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009394 config->format,
9395 channel_count,
9396 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009397 /* prevent division-by-zero */
9398 if (frame_size == 0) {
9399 ALOGE("%s: Error frame_size==0", __func__);
9400 ret = -EINVAL;
9401 goto err_open;
9402 }
9403
Revathi Uddarajud2634032017-12-07 14:42:34 +05309404 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009405 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009406
Revathi Uddarajud2634032017-12-07 14:42:34 +05309407 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9408 /* optionally use VOIP usecase depending on config(s) */
9409 ret = adev_update_voice_comm_input_stream(in, config);
9410 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009411
Revathi Uddarajud2634032017-12-07 14:42:34 +05309412 if (ret) {
9413 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9414 goto err_open;
9415 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009416 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309417
9418 /* assign concurrent capture usecase if record has to caried out from
9419 * actual hardware input source */
9420 if (audio_extn_is_concurrent_capture_enabled() &&
9421 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309422 /* Acquire lock to avoid two concurrent use cases initialized to
9423 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009424
Samyak Jainc37062f2019-04-25 18:41:06 +05309425 if (in->usecase == USECASE_AUDIO_RECORD) {
9426 pthread_mutex_lock(&adev->lock);
9427 if (!(adev->pcm_record_uc_state)) {
9428 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9429 adev->pcm_record_uc_state = 1;
9430 pthread_mutex_unlock(&adev->lock);
9431 } else {
9432 pthread_mutex_unlock(&adev->lock);
9433 /* Assign compress record use case for second record */
9434 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9435 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9436 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9437 if (audio_extn_cin_applicable_stream(in)) {
9438 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309439 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309440 if (ret)
9441 goto err_open;
9442 }
9443 }
9444 }
kunleiz28c73e72019-03-27 17:24:04 +08009445 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009446 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309447 if (audio_extn_ssr_get_stream() != in)
9448 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009449
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009450 in->sample_rate = in->config.rate;
9451
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309452 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9453 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009454 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009455 in->sample_rate, in->bit_width,
9456 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309457 register_format(in->format, in->supported_formats);
9458 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9459 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309460
Aalique Grahame22e49102018-12-18 14:23:57 -08009461 in->error_log = error_log_create(
9462 ERROR_LOG_ENTRIES,
9463 1000000000 /* aggregate consecutive identical errors within one second */);
9464
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009465 /* This stream could be for sound trigger lab,
9466 get sound trigger pcm if present */
9467 audio_extn_sound_trigger_check_and_get_session(in);
9468
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309469 lock_input_stream(in);
9470 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9471 pthread_mutex_lock(&adev->lock);
9472 in->card_status = adev->card_status;
9473 pthread_mutex_unlock(&adev->lock);
9474 pthread_mutex_unlock(&in->lock);
9475
Aalique Grahame22e49102018-12-18 14:23:57 -08009476 stream_app_type_cfg_init(&in->app_type_cfg);
9477
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009478 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009479
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009480 ret = io_streams_map_insert(adev, &in->stream.common,
9481 handle, AUDIO_PATCH_HANDLE_NONE);
9482 if (ret != 0)
9483 goto err_open;
9484
Derek Chenf939fb72018-11-13 13:34:41 -08009485 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9486 calloc(1, sizeof(streams_input_ctxt_t));
9487 if (in_ctxt == NULL) {
9488 ALOGE("%s fail to allocate input ctxt", __func__);
9489 ret = -ENOMEM;
9490 goto err_open;
9491 }
9492 in_ctxt->input = in;
9493
9494 pthread_mutex_lock(&adev->lock);
9495 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9496 pthread_mutex_unlock(&adev->lock);
9497
Eric Laurent994a6932013-07-17 11:51:42 -07009498 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009499 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009500
9501err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309502 if (in->usecase == USECASE_AUDIO_RECORD) {
9503 pthread_mutex_lock(&adev->lock);
9504 adev->pcm_record_uc_state = 0;
9505 pthread_mutex_unlock(&adev->lock);
9506 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009507 free(in);
9508 *stream_in = NULL;
9509 return ret;
9510}
9511
9512static void adev_close_input_stream(struct audio_hw_device *dev,
9513 struct audio_stream_in *stream)
9514{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009515 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009516 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009517 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309518
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309519 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009520
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009521 if (in == NULL) {
9522 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9523 return;
9524 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009525 io_streams_map_remove(adev, in->capture_handle);
9526
kunleiz70e57612018-12-28 17:50:23 +08009527 /* must deregister from sndmonitor first to prevent races
9528 * between the callback and close_stream
9529 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309530 audio_extn_snd_mon_unregister_listener(stream);
9531
kunleiz70e57612018-12-28 17:50:23 +08009532 /* Disable echo reference if there are no active input, hfp call
9533 * and sound trigger while closing input stream
9534 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009535 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009536 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009537 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9538 struct listnode out_devices;
9539 list_init(&out_devices);
9540 platform_set_echo_reference(adev, false, &out_devices);
9541 } else
kunleiz70e57612018-12-28 17:50:23 +08009542 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309543
Weiyin Jiang2995f662019-04-17 14:25:12 +08009544 error_log_destroy(in->error_log);
9545 in->error_log = NULL;
9546
Pallavid7c7a272018-01-16 11:22:55 +05309547
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009548 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309549 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009550 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309551 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009552 if (ret != 0)
9553 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9554 __func__, ret);
9555 } else
9556 in_standby(&stream->common);
9557
Revathi Uddarajud2634032017-12-07 14:42:34 +05309558 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309559 if (in->usecase == USECASE_AUDIO_RECORD) {
9560 adev->pcm_record_uc_state = 0;
9561 }
9562
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009563 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9564 adev->enable_voicerx = false;
9565 }
9566
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009567 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009568 audio_extn_ssr_deinit();
9569 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009570
Garmond Leunge2433c32017-09-28 21:51:22 -07009571 if (audio_extn_ffv_get_stream() == in) {
9572 audio_extn_ffv_stream_deinit();
9573 }
9574
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309575 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009576 audio_extn_compr_cap_format_supported(in->config.format))
9577 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309578
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309579 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309580 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009581
Mingming Yinfd7607b2016-01-22 12:48:44 -08009582 if (in->is_st_session) {
9583 ALOGV("%s: sound trigger pcm stop lab", __func__);
9584 audio_extn_sound_trigger_stop_lab(in);
9585 }
Derek Chenf939fb72018-11-13 13:34:41 -08009586 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9587 if (in_ctxt != NULL) {
9588 list_remove(&in_ctxt->list);
9589 free(in_ctxt);
9590 } else {
9591 ALOGW("%s, input stream already closed", __func__);
9592 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009593 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309594 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009595 return;
9596}
9597
Aalique Grahame22e49102018-12-18 14:23:57 -08009598/* verifies input and output devices and their capabilities.
9599 *
9600 * This verification is required when enabling extended bit-depth or
9601 * sampling rates, as not all qcom products support it.
9602 *
9603 * Suitable for calling only on initialization such as adev_open().
9604 * It fills the audio_device use_case_table[] array.
9605 *
9606 * Has a side-effect that it needs to configure audio routing / devices
9607 * in order to power up the devices and read the device parameters.
9608 * It does not acquire any hw device lock. Should restore the devices
9609 * back to "normal state" upon completion.
9610 */
9611static int adev_verify_devices(struct audio_device *adev)
9612{
9613 /* enumeration is a bit difficult because one really wants to pull
9614 * the use_case, device id, etc from the hidden pcm_device_table[].
9615 * In this case there are the following use cases and device ids.
9616 *
9617 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9618 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9619 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9620 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9621 * [USECASE_AUDIO_RECORD] = {0, 0},
9622 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9623 * [USECASE_VOICE_CALL] = {2, 2},
9624 *
9625 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9626 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9627 */
9628
9629 /* should be the usecases enabled in adev_open_input_stream() */
9630 static const int test_in_usecases[] = {
9631 USECASE_AUDIO_RECORD,
9632 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9633 };
9634 /* should be the usecases enabled in adev_open_output_stream()*/
9635 static const int test_out_usecases[] = {
9636 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9637 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9638 };
9639 static const usecase_type_t usecase_type_by_dir[] = {
9640 PCM_PLAYBACK,
9641 PCM_CAPTURE,
9642 };
9643 static const unsigned flags_by_dir[] = {
9644 PCM_OUT,
9645 PCM_IN,
9646 };
9647
9648 size_t i;
9649 unsigned dir;
9650 const unsigned card_id = adev->snd_card;
9651
9652 for (dir = 0; dir < 2; ++dir) {
9653 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9654 const unsigned flags_dir = flags_by_dir[dir];
9655 const size_t testsize =
9656 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9657 const int *testcases =
9658 dir ? test_in_usecases : test_out_usecases;
9659 const audio_devices_t audio_device =
9660 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9661
9662 for (i = 0; i < testsize; ++i) {
9663 const audio_usecase_t audio_usecase = testcases[i];
9664 int device_id;
9665 struct pcm_params **pparams;
9666 struct stream_out out;
9667 struct stream_in in;
9668 struct audio_usecase uc_info;
9669 int retval;
9670
9671 pparams = &adev->use_case_table[audio_usecase];
9672 pcm_params_free(*pparams); /* can accept null input */
9673 *pparams = NULL;
9674
9675 /* find the device ID for the use case (signed, for error) */
9676 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9677 if (device_id < 0)
9678 continue;
9679
9680 /* prepare structures for device probing */
9681 memset(&uc_info, 0, sizeof(uc_info));
9682 uc_info.id = audio_usecase;
9683 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009684 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009685 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009686 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009687 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009688 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009689 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9690 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009691 }
9692 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009693 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009694 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009695 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009696 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009697 uc_info.in_snd_device = SND_DEVICE_NONE;
9698 uc_info.out_snd_device = SND_DEVICE_NONE;
9699 list_add_tail(&adev->usecase_list, &uc_info.list);
9700
9701 /* select device - similar to start_(in/out)put_stream() */
9702 retval = select_devices(adev, audio_usecase);
9703 if (retval >= 0) {
9704 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9705#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009706 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009707 if (*pparams) {
9708 ALOGV("%s: (%s) card %d device %d", __func__,
9709 dir ? "input" : "output", card_id, device_id);
9710 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9711 } else {
9712 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9713 }
9714#endif
9715 }
9716
9717 /* deselect device - similar to stop_(in/out)put_stream() */
9718 /* 1. Get and set stream specific mixer controls */
9719 retval = disable_audio_route(adev, &uc_info);
9720 /* 2. Disable the rx device */
9721 retval = disable_snd_device(adev,
9722 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9723 list_remove(&uc_info.list);
9724 }
9725 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009726 return 0;
9727}
9728
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009729int update_patch(unsigned int num_sources,
9730 const struct audio_port_config *sources,
9731 unsigned int num_sinks,
9732 const struct audio_port_config *sinks,
9733 audio_patch_handle_t handle,
9734 struct audio_patch_info *p_info,
9735 patch_type_t patch_type, bool new_patch)
9736{
9737 ALOGD("%s: enter", __func__);
9738
9739 if (p_info == NULL) {
9740 ALOGE("%s: Invalid patch pointer", __func__);
9741 return -EINVAL;
9742 }
9743
9744 if (new_patch) {
9745 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9746 if (p_info->patch == NULL) {
9747 ALOGE("%s: Could not allocate patch", __func__);
9748 return -ENOMEM;
9749 }
9750 }
9751
9752 p_info->patch->id = handle;
9753 p_info->patch->num_sources = num_sources;
9754 p_info->patch->num_sinks = num_sinks;
9755
9756 for (int i = 0; i < num_sources; i++)
9757 p_info->patch->sources[i] = sources[i];
9758 for (int i = 0; i < num_sinks; i++)
9759 p_info->patch->sinks[i] = sinks[i];
9760
9761 p_info->patch_type = patch_type;
9762 return 0;
9763}
9764
9765audio_patch_handle_t generate_patch_handle()
9766{
9767 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9768 if (++patch_handle < 0)
9769 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9770 return patch_handle;
9771}
9772
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309773int adev_create_audio_patch(struct audio_hw_device *dev,
9774 unsigned int num_sources,
9775 const struct audio_port_config *sources,
9776 unsigned int num_sinks,
9777 const struct audio_port_config *sinks,
9778 audio_patch_handle_t *handle)
9779{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009780 int ret = 0;
9781 struct audio_device *adev = (struct audio_device *)dev;
9782 struct audio_patch_info *p_info = NULL;
9783 patch_type_t patch_type = PATCH_NONE;
9784 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9785 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9786 struct audio_stream_info *s_info = NULL;
9787 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009788 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009789 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9790 bool new_patch = false;
9791 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309792
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009793 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9794 num_sources, num_sinks, *handle);
9795
9796 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9797 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9798 ALOGE("%s: Invalid patch arguments", __func__);
9799 ret = -EINVAL;
9800 goto done;
9801 }
9802
9803 if (num_sources > 1) {
9804 ALOGE("%s: Multiple sources are not supported", __func__);
9805 ret = -EINVAL;
9806 goto done;
9807 }
9808
9809 if (sources == NULL || sinks == NULL) {
9810 ALOGE("%s: Invalid sources or sinks port config", __func__);
9811 ret = -EINVAL;
9812 goto done;
9813 }
9814
9815 ALOGV("%s: source role %d, source type %d", __func__,
9816 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009817 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009818
9819 // Populate source/sink information and fetch stream info
9820 switch (sources[0].type) {
9821 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9822 device_type = sources[0].ext.device.type;
9823 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009824 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009825 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9826 patch_type = PATCH_CAPTURE;
9827 io_handle = sinks[0].ext.mix.handle;
9828 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009829 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009830 __func__, device_type, io_handle);
9831 } else {
9832 // Device to device patch is not implemented.
9833 // This space will need changes if audio HAL
9834 // handles device to device patches in the future.
9835 patch_type = PATCH_DEVICE_LOOPBACK;
9836 }
9837 break;
9838 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9839 io_handle = sources[0].ext.mix.handle;
9840 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009841 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009842 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009843 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009844 }
9845 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009846 ALOGD("%s: Playback patch from mix handle %d to device %x",
9847 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009848 break;
9849 case AUDIO_PORT_TYPE_SESSION:
9850 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009851 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9852 ret = -EINVAL;
9853 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009854 }
9855
9856 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009857
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009858 // Generate patch info and update patch
9859 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009860 *handle = generate_patch_handle();
9861 p_info = (struct audio_patch_info *)
9862 calloc(1, sizeof(struct audio_patch_info));
9863 if (p_info == NULL) {
9864 ALOGE("%s: Failed to allocate memory", __func__);
9865 pthread_mutex_unlock(&adev->lock);
9866 ret = -ENOMEM;
9867 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009868 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009869 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009870 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009871 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009872 if (p_info == NULL) {
9873 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9874 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009875 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009876 ret = -EINVAL;
9877 goto done;
9878 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009879 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009880 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009881 *handle, p_info, patch_type, new_patch);
9882
9883 // Fetch stream info of associated mix for playback or capture patches
9884 if (p_info->patch_type == PATCH_PLAYBACK ||
9885 p_info->patch_type == PATCH_CAPTURE) {
9886 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9887 if (s_info == NULL) {
9888 ALOGE("%s: Failed to obtain stream info", __func__);
9889 if (new_patch)
9890 free(p_info);
9891 pthread_mutex_unlock(&adev->lock);
9892 ret = -EINVAL;
9893 goto done;
9894 }
9895 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9896 s_info->patch_handle = *handle;
9897 stream = s_info->stream;
9898 }
9899 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009900
9901 // Update routing for stream
9902 if (stream != NULL) {
9903 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009904 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009905 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009906 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009907 if (ret < 0) {
9908 pthread_mutex_lock(&adev->lock);
9909 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9910 if (new_patch)
9911 free(p_info);
9912 pthread_mutex_unlock(&adev->lock);
9913 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9914 goto done;
9915 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009916 }
9917
9918 // Add new patch to patch map
9919 if (!ret && new_patch) {
9920 pthread_mutex_lock(&adev->lock);
9921 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009922 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009923 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009924 }
9925
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009926done:
9927 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009928 num_sources,
9929 sources,
9930 num_sinks,
9931 sinks,
9932 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009933 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009934 num_sources,
9935 sources,
9936 num_sinks,
9937 sinks,
9938 handle);
9939 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309940}
9941
9942int adev_release_audio_patch(struct audio_hw_device *dev,
9943 audio_patch_handle_t handle)
9944{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009945 struct audio_device *adev = (struct audio_device *) dev;
9946 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009947 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009948 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -08009949
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009950 if (handle == AUDIO_PATCH_HANDLE_NONE) {
9951 ALOGE("%s: Invalid patch handle %d", __func__, handle);
9952 ret = -EINVAL;
9953 goto done;
9954 }
9955
9956 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009957 pthread_mutex_lock(&adev->lock);
9958 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009959 if (p_info == NULL) {
9960 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009961 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009962 ret = -EINVAL;
9963 goto done;
9964 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009965 struct audio_patch *patch = p_info->patch;
9966 if (patch == NULL) {
9967 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009968 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009969 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009970 goto done;
9971 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009972 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9973 switch (patch->sources[0].type) {
9974 case AUDIO_PORT_TYPE_MIX:
9975 io_handle = patch->sources[0].ext.mix.handle;
9976 break;
9977 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009978 if (p_info->patch_type == PATCH_CAPTURE)
9979 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009980 break;
9981 case AUDIO_PORT_TYPE_SESSION:
9982 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009983 pthread_mutex_unlock(&adev->lock);
9984 ret = -EINVAL;
9985 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009986 }
9987
9988 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009989 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009990 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009991 if (patch_type == PATCH_PLAYBACK ||
9992 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009993 struct audio_stream_info *s_info =
9994 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9995 if (s_info == NULL) {
9996 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
9997 pthread_mutex_unlock(&adev->lock);
9998 goto done;
9999 }
10000 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10001 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010002 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010003 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010004
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010005 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010006 struct listnode devices;
10007 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010008 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010009 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010010 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010011 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010012 }
10013
10014 if (ret < 0)
10015 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10016
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010017done:
10018 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10019 audio_extn_auto_hal_release_audio_patch(dev, handle);
10020
10021 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010022 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010023}
10024
10025int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10026{
Derek Chenf13dd492018-11-13 14:53:51 -080010027 int ret = 0;
10028
10029 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10030 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10031 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010032}
10033
10034int adev_set_audio_port_config(struct audio_hw_device *dev,
10035 const struct audio_port_config *config)
10036{
Derek Chenf13dd492018-11-13 14:53:51 -080010037 int ret = 0;
10038
10039 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10040 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10041 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010042}
10043
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010044static int adev_dump(const audio_hw_device_t *device __unused,
10045 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010046{
10047 return 0;
10048}
10049
10050static int adev_close(hw_device_t *device)
10051{
Aalique Grahame22e49102018-12-18 14:23:57 -080010052 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010053 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010054
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010055 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010056 return 0;
10057
10058 pthread_mutex_lock(&adev_init_lock);
10059
10060 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010061 if (audio_extn_spkr_prot_is_enabled())
10062 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010063 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010064 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010065 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010066 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010067 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010068 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010069 audio_extn_utils_release_streams_cfg_lists(
10070 &adev->streams_output_cfg_list,
10071 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010072 if (audio_extn_qap_is_enabled())
10073 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010074 if (audio_extn_qaf_is_enabled())
10075 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010076 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010077 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010078 free(adev->snd_dev_ref_cnt);
10079 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010080 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10081 pcm_params_free(adev->use_case_table[i]);
10082 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010083 if (adev->adm_deinit)
10084 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010085 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010086 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010087 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010088 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010089 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010090 if (adev->device_cfg_params) {
10091 free(adev->device_cfg_params);
10092 adev->device_cfg_params = NULL;
10093 }
Derek Chend2530072014-11-24 12:39:14 -080010094 if(adev->ext_hw_plugin)
10095 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010096 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010097 free_map(adev->patch_map);
10098 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010099 free(device);
10100 adev = NULL;
10101 }
10102 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010103 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010104 return 0;
10105}
10106
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010107/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10108 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10109 * just that it _might_ work.
10110 */
10111static int period_size_is_plausible_for_low_latency(int period_size)
10112{
10113 switch (period_size) {
10114 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010115 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010116 case 240:
10117 case 320:
10118 case 480:
10119 return 1;
10120 default:
10121 return 0;
10122 }
10123}
10124
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010125static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10126{
10127 bool is_snd_card_status = false;
10128 bool is_ext_device_status = false;
10129 char value[32];
10130 int card = -1;
10131 card_status_t status;
10132
10133 if (cookie != adev || !parms)
10134 return;
10135
10136 if (!parse_snd_card_status(parms, &card, &status)) {
10137 is_snd_card_status = true;
10138 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10139 is_ext_device_status = true;
10140 } else {
10141 // not a valid event
10142 return;
10143 }
10144
10145 pthread_mutex_lock(&adev->lock);
10146 if (card == adev->snd_card || is_ext_device_status) {
10147 if (is_snd_card_status && adev->card_status != status) {
10148 adev->card_status = status;
10149 platform_snd_card_update(adev->platform, status);
10150 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010151 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010152 if (status == CARD_STATUS_OFFLINE)
10153 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010154 } else if (is_ext_device_status) {
10155 platform_set_parameters(adev->platform, parms);
10156 }
10157 }
10158 pthread_mutex_unlock(&adev->lock);
10159 return;
10160}
10161
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010162/* out and adev lock held */
10163static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10164{
10165 struct audio_usecase *uc_info;
10166 float left_p;
10167 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010168 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010169
10170 uc_info = get_usecase_from_list(adev, out->usecase);
10171 if (uc_info == NULL) {
10172 ALOGE("%s: Could not find the usecase (%d) in the list",
10173 __func__, out->usecase);
10174 return -EINVAL;
10175 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010176 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010177
10178 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10179 out->usecase, use_case_table[out->usecase]);
10180
10181 if (restore) {
10182 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010183 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010184 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010185 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10186 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010187 pthread_mutex_lock(&out->compr_mute_lock);
10188 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010189 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010190 out->a2dp_compress_mute = false;
10191 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10192 }
10193 pthread_mutex_unlock(&out->compr_mute_lock);
10194 }
10195 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010196 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10197 // mute compress stream if suspended
10198 pthread_mutex_lock(&out->compr_mute_lock);
10199 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010200 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010201 assign_devices(&devices, &out->device_list);
10202 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010203 left_p = out->volume_l;
10204 right_p = out->volume_r;
10205 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10206 compress_pause(out->compr);
10207 out_set_compr_volume(&out->stream, (float)0, (float)0);
10208 out->a2dp_compress_mute = true;
10209 select_devices(adev, out->usecase);
10210 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10211 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010212 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010213 out->volume_l = left_p;
10214 out->volume_r = right_p;
10215 }
Zhou Songc576a452019-09-09 14:17:40 +080010216 pthread_mutex_unlock(&out->compr_mute_lock);
10217 } else {
10218 // tear down a2dp path for non offloaded streams
10219 if (audio_extn_a2dp_source_is_suspended())
10220 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010221 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010222 }
10223 ALOGV("%s: exit", __func__);
10224 return 0;
10225}
10226
10227int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10228{
10229 int ret = 0;
10230
10231 lock_output_stream(out);
10232 pthread_mutex_lock(&adev->lock);
10233
10234 ret = check_a2dp_restore_l(adev, out, restore);
10235
10236 pthread_mutex_unlock(&adev->lock);
10237 pthread_mutex_unlock(&out->lock);
10238 return ret;
10239}
10240
Haynes Mathew George01156f92018-04-13 15:29:54 -070010241void adev_on_battery_status_changed(bool charging)
10242{
10243 pthread_mutex_lock(&adev->lock);
10244 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10245 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010246 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010247 pthread_mutex_unlock(&adev->lock);
10248}
10249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010250static int adev_open(const hw_module_t *module, const char *name,
10251 hw_device_t **device)
10252{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010253 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010254 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010255 char mixer_ctl_name[128] = {0};
10256 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010257
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010258 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010259 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10260
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010261 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010262 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010263 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010264 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010265 ALOGD("%s: returning existing instance of adev", __func__);
10266 ALOGD("%s: exit", __func__);
10267 pthread_mutex_unlock(&adev_init_lock);
10268 return 0;
10269 }
10270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010271 adev = calloc(1, sizeof(struct audio_device));
10272
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010273 if (!adev) {
10274 pthread_mutex_unlock(&adev_init_lock);
10275 return -ENOMEM;
10276 }
10277
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010278 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10279
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010280 // register audio ext hidl at the earliest
10281 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010282#ifdef DYNAMIC_LOG_ENABLED
10283 register_for_dynamic_logging("hal");
10284#endif
10285
Derek Chenf939fb72018-11-13 13:34:41 -080010286 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010287 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010288 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10289 maj_version = atoi(value);
10290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010291 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010292 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010293 adev->device.common.module = (struct hw_module_t *)module;
10294 adev->device.common.close = adev_close;
10295
10296 adev->device.init_check = adev_init_check;
10297 adev->device.set_voice_volume = adev_set_voice_volume;
10298 adev->device.set_master_volume = adev_set_master_volume;
10299 adev->device.get_master_volume = adev_get_master_volume;
10300 adev->device.set_master_mute = adev_set_master_mute;
10301 adev->device.get_master_mute = adev_get_master_mute;
10302 adev->device.set_mode = adev_set_mode;
10303 adev->device.set_mic_mute = adev_set_mic_mute;
10304 adev->device.get_mic_mute = adev_get_mic_mute;
10305 adev->device.set_parameters = adev_set_parameters;
10306 adev->device.get_parameters = adev_get_parameters;
10307 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10308 adev->device.open_output_stream = adev_open_output_stream;
10309 adev->device.close_output_stream = adev_close_output_stream;
10310 adev->device.open_input_stream = adev_open_input_stream;
10311 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010312 adev->device.create_audio_patch = adev_create_audio_patch;
10313 adev->device.release_audio_patch = adev_release_audio_patch;
10314 adev->device.get_audio_port = adev_get_audio_port;
10315 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010316 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010317 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010318
10319 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010320 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010321 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010322 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010323 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010324 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010325 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010326 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010327 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010328 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010329 /* Init audio and voice feature */
10330 audio_extn_feature_init();
10331 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010332 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010333 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010334 list_init(&adev->active_inputs_list);
10335 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010336 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010337 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10338 audio_extn_utils_hash_eq);
10339 if (!adev->io_streams_map) {
10340 ALOGE("%s: Could not create io streams map", __func__);
10341 ret = -ENOMEM;
10342 goto adev_open_err;
10343 }
10344 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10345 audio_extn_utils_hash_eq);
10346 if (!adev->patch_map) {
10347 ALOGE("%s: Could not create audio patch map", __func__);
10348 ret = -ENOMEM;
10349 goto adev_open_err;
10350 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010351 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010352 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010353 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010354 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010355 adev->perf_lock_opts[0] = 0x101;
10356 adev->perf_lock_opts[1] = 0x20E;
10357 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010358 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010359 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010360 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010361 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010362
Zhou Song68ebc352019-12-05 17:11:15 +080010363 audio_extn_perf_lock_init();
10364
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010365 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010366 adev->platform = platform_init(adev);
10367 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010368 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010369 ret = -EINVAL;
10370 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010371 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010372
Aalique Grahame22e49102018-12-18 14:23:57 -080010373 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010374 if (audio_extn_qap_is_enabled()) {
10375 ret = audio_extn_qap_init(adev);
10376 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010377 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010378 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010379 }
10380 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10381 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10382 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010383
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010384 if (audio_extn_qaf_is_enabled()) {
10385 ret = audio_extn_qaf_init(adev);
10386 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010387 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010388 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010389 }
10390
10391 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10392 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10393 }
10394
Derek Chenae7b0342019-02-08 15:17:04 -080010395 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010396 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10397
Eric Laurentc4aef752013-09-12 17:45:53 -070010398 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10399 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10400 if (adev->visualizer_lib == NULL) {
10401 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10402 } else {
10403 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10404 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010405 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010406 "visualizer_hal_start_output");
10407 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010408 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010409 "visualizer_hal_stop_output");
10410 }
10411 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010412 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010413 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010414 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010415 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010416 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010417 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010418
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010419 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10420 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10421 if (adev->offload_effects_lib == NULL) {
10422 ALOGE("%s: DLOPEN failed for %s", __func__,
10423 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10424 } else {
10425 ALOGV("%s: DLOPEN successful for %s", __func__,
10426 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10427 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010428 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010429 "offload_effects_bundle_hal_start_output");
10430 adev->offload_effects_stop_output =
10431 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10432 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010433 adev->offload_effects_set_hpx_state =
10434 (int (*)(bool))dlsym(adev->offload_effects_lib,
10435 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010436 adev->offload_effects_get_parameters =
10437 (void (*)(struct str_parms *, struct str_parms *))
10438 dlsym(adev->offload_effects_lib,
10439 "offload_effects_bundle_get_parameters");
10440 adev->offload_effects_set_parameters =
10441 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10442 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010443 }
10444 }
10445
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010446 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10447 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10448 if (adev->adm_lib == NULL) {
10449 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10450 } else {
10451 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10452 adev->adm_init = (adm_init_t)
10453 dlsym(adev->adm_lib, "adm_init");
10454 adev->adm_deinit = (adm_deinit_t)
10455 dlsym(adev->adm_lib, "adm_deinit");
10456 adev->adm_register_input_stream = (adm_register_input_stream_t)
10457 dlsym(adev->adm_lib, "adm_register_input_stream");
10458 adev->adm_register_output_stream = (adm_register_output_stream_t)
10459 dlsym(adev->adm_lib, "adm_register_output_stream");
10460 adev->adm_deregister_stream = (adm_deregister_stream_t)
10461 dlsym(adev->adm_lib, "adm_deregister_stream");
10462 adev->adm_request_focus = (adm_request_focus_t)
10463 dlsym(adev->adm_lib, "adm_request_focus");
10464 adev->adm_abandon_focus = (adm_abandon_focus_t)
10465 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010466 adev->adm_set_config = (adm_set_config_t)
10467 dlsym(adev->adm_lib, "adm_set_config");
10468 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10469 dlsym(adev->adm_lib, "adm_request_focus_v2");
10470 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10471 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10472 adev->adm_on_routing_change = (adm_on_routing_change_t)
10473 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010474 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10475 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010476 }
10477 }
10478
Aalique Grahame22e49102018-12-18 14:23:57 -080010479 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010480 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010481 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010482 //initialize this to false for now,
10483 //this will be set to true through set param
10484 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010485
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010486 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010487 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010488
10489 if (k_enable_extended_precision)
10490 adev_verify_devices(adev);
10491
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010492 adev->dsp_bit_width_enforce_mode =
10493 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010494
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010495 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10496 &adev->streams_output_cfg_list,
10497 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010498
Kiran Kandi910e1862013-10-29 13:29:42 -070010499 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010500
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010501 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010502 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010503 trial = atoi(value);
10504 if (period_size_is_plausible_for_low_latency(trial)) {
10505 pcm_config_low_latency.period_size = trial;
10506 pcm_config_low_latency.start_threshold = trial / 4;
10507 pcm_config_low_latency.avail_min = trial / 4;
10508 configured_low_latency_capture_period_size = trial;
10509 }
10510 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010511 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10512 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010513 trial = atoi(value);
10514 if (period_size_is_plausible_for_low_latency(trial)) {
10515 configured_low_latency_capture_period_size = trial;
10516 }
10517 }
10518
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010519 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10520
Eric Laurent4b084132018-10-19 17:33:43 -070010521 adev->camera_orientation = CAMERA_DEFAULT;
10522
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010523 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010524 af_period_multiplier = atoi(value);
10525 if (af_period_multiplier < 0)
10526 af_period_multiplier = 2;
10527 else if (af_period_multiplier > 4)
10528 af_period_multiplier = 4;
10529
10530 ALOGV("new period_multiplier = %d", af_period_multiplier);
10531 }
10532
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010533 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010534
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010535 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010536 pthread_mutex_unlock(&adev_init_lock);
10537
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010538 if (adev->adm_init)
10539 adev->adm_data = adev->adm_init();
10540
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010541 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010542 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010543
10544 audio_extn_snd_mon_init();
10545 pthread_mutex_lock(&adev->lock);
10546 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10547 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010548 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10549 /*
10550 * if the battery state callback happens before charging can be queried,
10551 * it will be guarded with the adev->lock held in the cb function and so
10552 * the callback value will reflect the latest state
10553 */
10554 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010555 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010556 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010557 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010558 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010559 /* Allocate memory for Device config params */
10560 adev->device_cfg_params = (struct audio_device_config_param*)
10561 calloc(platform_get_max_codec_backend(),
10562 sizeof(struct audio_device_config_param));
10563 if (adev->device_cfg_params == NULL)
10564 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010565
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010566 /*
10567 * Check if new PSPD matrix mixer control is supported. If not
10568 * supported, then set flag so that old mixer ctrl is sent while
10569 * sending pspd coefficients on older kernel version. Query mixer
10570 * control for default pcm id and channel value one.
10571 */
10572 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10573 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10574
10575 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10576 if (!ctl) {
10577 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10578 __func__, mixer_ctl_name);
10579 adev->use_old_pspd_mix_ctrl = true;
10580 }
10581
Eric Laurent994a6932013-07-17 11:51:42 -070010582 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010583 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010584
10585adev_open_err:
10586 free_map(adev->patch_map);
10587 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010588 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010589 pthread_mutex_destroy(&adev->lock);
10590 free(adev);
10591 adev = NULL;
10592 *device = NULL;
10593 pthread_mutex_unlock(&adev_init_lock);
10594 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010595}
10596
10597static struct hw_module_methods_t hal_module_methods = {
10598 .open = adev_open,
10599};
10600
10601struct audio_module HAL_MODULE_INFO_SYM = {
10602 .common = {
10603 .tag = HARDWARE_MODULE_TAG,
10604 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10605 .hal_api_version = HARDWARE_HAL_API_VERSION,
10606 .id = AUDIO_HARDWARE_MODULE_ID,
10607 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010608 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010609 .methods = &hal_module_methods,
10610 },
10611};