blob: 5ddd193bd2863521f0763c9a32a8266ccbbc6e80 [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 Chen1bcdc6b2020-02-06 22:44:53 -0800413 [USECASE_AUDIO_PLAYBACK_FRONT_PASSENGER] = "front-passenger-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700414 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530415 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700416};
417
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700418static const audio_usecase_t offload_usecases[] = {
419 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700420 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
421 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
422 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
426 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
427 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700428};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800429
Varun Balaraje49253e2017-07-06 19:48:56 +0530430static const audio_usecase_t interactive_usecases[] = {
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
432 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
437 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
438 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
439};
440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800441#define STRING_TO_ENUM(string) { #string, string }
442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443struct string_to_enum {
444 const char *name;
445 uint32_t value;
446};
447
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700448static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800450 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
455 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700457 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
458 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
459 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
461 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
466 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
467 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800468};
469
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700470static const struct string_to_enum formats_name_to_enum_table[] = {
471 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
472 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
473 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700474 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
475 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
476 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700477 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800478 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
479 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700480 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800481};
482
483//list of all supported sample rates by HDMI specification.
484static const int out_hdmi_sample_rates[] = {
485 32000, 44100, 48000, 88200, 96000, 176400, 192000,
486};
487
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700488static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800489 STRING_TO_ENUM(32000),
490 STRING_TO_ENUM(44100),
491 STRING_TO_ENUM(48000),
492 STRING_TO_ENUM(88200),
493 STRING_TO_ENUM(96000),
494 STRING_TO_ENUM(176400),
495 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800496 STRING_TO_ENUM(352800),
497 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700498};
499
Carter Hsu2e429db2019-05-14 18:50:52 +0800500struct in_effect_list {
501 struct listnode list;
502 effect_handle_t handle;
503};
504
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700505static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700506static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700507static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700508//cache last MBDRC cal step level
509static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700510
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530511static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
512static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700513static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800514static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530515static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530516
Derek Chen6f293672019-04-01 01:40:24 -0700517static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
518static void in_snd_mon_cb(void * stream, struct str_parms * parms);
519static void out_snd_mon_cb(void * stream, struct str_parms * parms);
520
Zhou Song331c8e52019-08-26 14:16:12 +0800521static int configure_btsco_sample_rate(snd_device_t snd_device);
522
Vatsal Buchac09ae062018-11-14 13:25:08 +0530523#ifdef AUDIO_FEATURE_ENABLED_GCOV
524extern void __gcov_flush();
525static void enable_gcov()
526{
527 __gcov_flush();
528}
529#else
530static void enable_gcov()
531{
532}
533#endif
534
justinweng20fb6d82019-02-21 18:49:00 -0700535static int in_set_microphone_direction(const struct audio_stream_in *stream,
536 audio_microphone_direction_t dir);
537static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
538
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700539static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
540 int flags __unused)
541{
542 int dir = 0;
543 switch (uc_id) {
544 case USECASE_AUDIO_RECORD_LOW_LATENCY:
545 dir = 1;
546 case USECASE_AUDIO_PLAYBACK_ULL:
547 break;
548 default:
549 return false;
550 }
551
552 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
553 PCM_PLAYBACK : PCM_CAPTURE);
554 if (adev->adm_is_noirq_avail)
555 return adev->adm_is_noirq_avail(adev->adm_data,
556 adev->snd_card, dev_id, dir);
557 return false;
558}
559
560static void register_out_stream(struct stream_out *out)
561{
562 struct audio_device *adev = out->dev;
563 if (is_offload_usecase(out->usecase) ||
564 !adev->adm_register_output_stream)
565 return;
566
567 // register stream first for backward compatibility
568 adev->adm_register_output_stream(adev->adm_data,
569 out->handle,
570 out->flags);
571
572 if (!adev->adm_set_config)
573 return;
574
575 if (out->realtime)
576 adev->adm_set_config(adev->adm_data,
577 out->handle,
578 out->pcm, &out->config);
579}
580
581static void register_in_stream(struct stream_in *in)
582{
583 struct audio_device *adev = in->dev;
584 if (!adev->adm_register_input_stream)
585 return;
586
587 adev->adm_register_input_stream(adev->adm_data,
588 in->capture_handle,
589 in->flags);
590
591 if (!adev->adm_set_config)
592 return;
593
594 if (in->realtime)
595 adev->adm_set_config(adev->adm_data,
596 in->capture_handle,
597 in->pcm,
598 &in->config);
599}
600
601static void request_out_focus(struct stream_out *out, long ns)
602{
603 struct audio_device *adev = out->dev;
604
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700605 if (adev->adm_request_focus_v2)
606 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
607 else if (adev->adm_request_focus)
608 adev->adm_request_focus(adev->adm_data, out->handle);
609}
610
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700611static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700612{
613 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700614 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700615
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700616 if (adev->adm_request_focus_v2_1)
617 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
618 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700619 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
620 else if (adev->adm_request_focus)
621 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700622
623 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700624}
625
626static void release_out_focus(struct stream_out *out)
627{
628 struct audio_device *adev = out->dev;
629
630 if (adev->adm_abandon_focus)
631 adev->adm_abandon_focus(adev->adm_data, out->handle);
632}
633
634static void release_in_focus(struct stream_in *in)
635{
636 struct audio_device *adev = in->dev;
637 if (adev->adm_abandon_focus)
638 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
639}
640
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530641static int parse_snd_card_status(struct str_parms *parms, int *card,
642 card_status_t *status)
643{
644 char value[32]={0};
645 char state[32]={0};
646
647 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
648 if (ret < 0)
649 return -1;
650
651 // sscanf should be okay as value is of max length 32.
652 // same as sizeof state.
653 if (sscanf(value, "%d,%s", card, state) < 2)
654 return -1;
655
656 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
657 CARD_STATUS_OFFLINE;
658 return 0;
659}
660
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700661static inline void adjust_frames_for_device_delay(struct stream_out *out,
662 uint32_t *dsp_frames) {
663 // Adjustment accounts for A2dp encoder latency with offload usecases
664 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800665 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700666 unsigned long offset =
667 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
668 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
669 }
670}
671
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700672static inline bool free_entry(void *key __unused,
673 void *value, void *context __unused)
674{
675 free(value);
676 return true;
677}
678
679static inline void free_map(Hashmap *map)
680{
681 if (map) {
682 hashmapForEach(map, free_entry, (void *) NULL);
683 hashmapFree(map);
684 }
685}
686
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800687static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700688 audio_patch_handle_t patch_handle)
689{
690 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
691 return;
692
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700693 struct audio_patch_info *p_info =
694 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
695 if (p_info) {
696 ALOGV("%s: Remove patch %d", __func__, patch_handle);
697 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
698 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700699 free(p_info);
700 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700701}
702
703static inline int io_streams_map_insert(struct audio_device *adev,
704 struct audio_stream *stream,
705 audio_io_handle_t handle,
706 audio_patch_handle_t patch_handle)
707{
708 struct audio_stream_info *s_info =
709 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
710
711 if (s_info == NULL) {
712 ALOGE("%s: Could not allocate stream info", __func__);
713 return -ENOMEM;
714 }
715 s_info->stream = stream;
716 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700717
718 pthread_mutex_lock(&adev->lock);
719 struct audio_stream_info *stream_info =
720 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700721 if (stream_info != NULL)
722 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800723 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700724 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
725 return 0;
726}
727
728static inline void io_streams_map_remove(struct audio_device *adev,
729 audio_io_handle_t handle)
730{
731 pthread_mutex_lock(&adev->lock);
732 struct audio_stream_info *s_info =
733 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700734 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800735 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700736 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800737 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700738 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800739done:
740 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700741 return;
742}
743
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800744static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700745 audio_patch_handle_t handle)
746{
747 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700748 p_info = (struct audio_patch_info *)
749 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700750 return p_info;
751}
752
vivek mehtaa76401a2015-04-24 14:12:15 -0700753__attribute__ ((visibility ("default")))
754bool audio_hw_send_gain_dep_calibration(int level) {
755 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700756 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700757
758 pthread_mutex_lock(&adev_init_lock);
759
760 if (adev != NULL && adev->platform != NULL) {
761 pthread_mutex_lock(&adev->lock);
762 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700763
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530764 // cache level info for any of the use case which
765 // was not started.
766 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700767
vivek mehtaa76401a2015-04-24 14:12:15 -0700768 pthread_mutex_unlock(&adev->lock);
769 } else {
770 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
771 }
772
773 pthread_mutex_unlock(&adev_init_lock);
774
775 return ret_val;
776}
777
Ashish Jain5106d362016-05-11 19:23:33 +0530778static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
779{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800780 bool gapless_enabled = false;
781 const char *mixer_ctl_name = "Compress Gapless Playback";
782 struct mixer_ctl *ctl;
783
784 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700785 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530786
787 /*Disable gapless if its AV playback*/
788 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800789
790 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
791 if (!ctl) {
792 ALOGE("%s: Could not get ctl for mixer cmd - %s",
793 __func__, mixer_ctl_name);
794 return -EINVAL;
795 }
796
797 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
798 ALOGE("%s: Could not set gapless mode %d",
799 __func__, gapless_enabled);
800 return -EINVAL;
801 }
802 return 0;
803}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700804
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700805__attribute__ ((visibility ("default")))
806int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
807 int table_size) {
808 int ret_val = 0;
809 ALOGV("%s: enter ... ", __func__);
810
811 pthread_mutex_lock(&adev_init_lock);
812 if (adev == NULL) {
813 ALOGW("%s: adev is NULL .... ", __func__);
814 goto done;
815 }
816
817 pthread_mutex_lock(&adev->lock);
818 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
819 pthread_mutex_unlock(&adev->lock);
820done:
821 pthread_mutex_unlock(&adev_init_lock);
822 ALOGV("%s: exit ... ", __func__);
823 return ret_val;
824}
825
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800826bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800827{
828 bool ret = false;
829 ALOGV("%s: enter ...", __func__);
830
831 pthread_mutex_lock(&adev_init_lock);
832
833 if (adev != NULL && adev->platform != NULL) {
834 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800835 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800836 pthread_mutex_unlock(&adev->lock);
837 }
838
839 pthread_mutex_unlock(&adev_init_lock);
840
841 ALOGV("%s: exit with ret %d", __func__, ret);
842 return ret;
843}
Aalique Grahame22e49102018-12-18 14:23:57 -0800844
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700845static bool is_supported_format(audio_format_t format)
846{
Eric Laurent86e17132013-09-12 17:49:30 -0700847 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530848 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530849 format == AUDIO_FORMAT_AAC_LC ||
850 format == AUDIO_FORMAT_AAC_HE_V1 ||
851 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530852 format == AUDIO_FORMAT_AAC_ADTS_LC ||
853 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
854 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530855 format == AUDIO_FORMAT_AAC_LATM_LC ||
856 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
857 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530858 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
859 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530860 format == AUDIO_FORMAT_PCM_FLOAT ||
861 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700862 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530863 format == AUDIO_FORMAT_AC3 ||
864 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700865 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530866 format == AUDIO_FORMAT_DTS ||
867 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800868 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530869 format == AUDIO_FORMAT_ALAC ||
870 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530871 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530872 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800873 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530874 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700875 format == AUDIO_FORMAT_APTX ||
876 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800877 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700878
879 return false;
880}
881
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700882static inline bool is_mmap_usecase(audio_usecase_t uc_id)
883{
884 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
885 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
886}
887
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700888static inline bool is_valid_volume(float left, float right)
889{
890 return ((left >= 0.0f && right >= 0.0f) ? true : false);
891}
892
Avinash Vaish71a8b972014-07-24 15:36:33 +0530893static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
894 struct audio_usecase *uc_info)
895{
896 struct listnode *node;
897 struct audio_usecase *usecase;
898
899 if (uc_info == NULL)
900 return -EINVAL;
901
902 /* Re-route all voice usecases on the shared backend other than the
903 specified usecase to new snd devices */
904 list_for_each(node, &adev->usecase_list) {
905 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800906 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530907 enable_audio_route(adev, usecase);
908 }
909 return 0;
910}
911
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530912static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530913{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530914 ALOGV("%s", __func__);
915 audio_route_apply_and_update_path(adev->audio_route,
916 "asrc-mode");
917 adev->asrc_mode_enabled = true;
918}
919
920static void disable_asrc_mode(struct audio_device *adev)
921{
922 ALOGV("%s", __func__);
923 audio_route_reset_and_update_path(adev->audio_route,
924 "asrc-mode");
925 adev->asrc_mode_enabled = false;
926}
927
928/*
929 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
930 * 44.1 or Native DSD backends are enabled for any of current use case.
931 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
932 * - Disable current mix path use case(Headphone backend) and re-enable it with
933 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
934 * e.g. Naitve DSD or Headphone 44.1 -> + 48
935 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530936static void check_and_set_asrc_mode(struct audio_device *adev,
937 struct audio_usecase *uc_info,
938 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530939{
940 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530941 int i, num_new_devices = 0;
942 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
943 /*
944 *Split snd device for new combo use case
945 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
946 */
947 if (platform_split_snd_device(adev->platform,
948 snd_device,
949 &num_new_devices,
950 split_new_snd_devices) == 0) {
951 for (i = 0; i < num_new_devices; i++)
952 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
953 } else {
954 int new_backend_idx = platform_get_backend_index(snd_device);
955 if (((new_backend_idx == HEADPHONE_BACKEND) ||
956 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
957 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
958 !adev->asrc_mode_enabled) {
959 struct listnode *node = NULL;
960 struct audio_usecase *uc = NULL;
961 struct stream_out *curr_out = NULL;
962 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
963 int i, num_devices, ret = 0;
964 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530965
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530966 list_for_each(node, &adev->usecase_list) {
967 uc = node_to_item(node, struct audio_usecase, list);
968 curr_out = (struct stream_out*) uc->stream.out;
969 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
970 /*
971 *Split snd device for existing combo use case
972 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
973 */
974 ret = platform_split_snd_device(adev->platform,
975 uc->out_snd_device,
976 &num_devices,
977 split_snd_devices);
978 if (ret < 0 || num_devices == 0) {
979 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
980 split_snd_devices[0] = uc->out_snd_device;
981 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800982 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530983 for (i = 0; i < num_devices; i++) {
984 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
985 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
986 if((new_backend_idx == HEADPHONE_BACKEND) &&
987 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
988 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
989 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
990 __func__);
991 enable_asrc_mode(adev);
992 break;
993 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
994 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
995 (usecase_backend_idx == HEADPHONE_BACKEND)) {
996 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
997 __func__);
998 disable_audio_route(adev, uc);
999 disable_snd_device(adev, uc->out_snd_device);
1000 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1001 if (new_backend_idx == DSD_NATIVE_BACKEND)
1002 audio_route_apply_and_update_path(adev->audio_route,
1003 "hph-true-highquality-mode");
1004 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1005 (curr_out->bit_width >= 24))
1006 audio_route_apply_and_update_path(adev->audio_route,
1007 "hph-highquality-mode");
1008 enable_asrc_mode(adev);
1009 enable_snd_device(adev, uc->out_snd_device);
1010 enable_audio_route(adev, uc);
1011 break;
1012 }
1013 }
1014 // reset split devices count
1015 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001016 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301017 if (adev->asrc_mode_enabled)
1018 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301019 }
1020 }
1021 }
1022}
1023
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001024static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1025 struct audio_effect_config effect_config,
1026 unsigned int param_value)
1027{
1028 char mixer_ctl_name[] = "Audio Effect";
1029 struct mixer_ctl *ctl;
1030 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001031 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001032
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001033 if (in == NULL) {
1034 ALOGE("%s: active input stream is NULL", __func__);
1035 return -EINVAL;
1036 }
1037
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001038 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1039 if (!ctl) {
1040 ALOGE("%s: Could not get mixer ctl - %s",
1041 __func__, mixer_ctl_name);
1042 return -EINVAL;
1043 }
1044
1045 set_values[0] = 1; //0:Rx 1:Tx
1046 set_values[1] = in->app_type_cfg.app_type;
1047 set_values[2] = (long)effect_config.module_id;
1048 set_values[3] = (long)effect_config.instance_id;
1049 set_values[4] = (long)effect_config.param_id;
1050 set_values[5] = param_value;
1051
1052 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1053
1054 return 0;
1055
1056}
1057
1058static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1059 int effect_type, unsigned int *param_value)
1060{
1061 int ret = 0;
1062 struct audio_effect_config other_effect_config;
1063 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001064 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001065
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001066 if (in == NULL) {
1067 ALOGE("%s: active input stream is NULL", __func__);
1068 return -EINVAL;
1069 }
1070
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001071 usecase = get_usecase_from_list(adev, in->usecase);
1072 if (!usecase)
1073 return -EINVAL;
1074
1075 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1076 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1077 if (ret < 0) {
1078 ALOGE("%s Failed to get effect params %d", __func__, ret);
1079 return ret;
1080 }
1081
1082 if (module_id == other_effect_config.module_id) {
1083 //Same module id for AEC/NS. Values need to be combined
1084 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1085 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1086 *param_value |= other_effect_config.param_value;
1087 }
1088 }
1089
1090 return ret;
1091}
1092
1093static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301094{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001095 struct audio_effect_config effect_config;
1096 struct audio_usecase *usecase = NULL;
1097 int ret = 0;
1098 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001099 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001100
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001101 if(!voice_extn_is_dynamic_ecns_enabled())
1102 return ENOSYS;
1103
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001104 if (!in) {
1105 ALOGE("%s: Invalid input stream", __func__);
1106 return -EINVAL;
1107 }
1108
1109 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1110
1111 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001112 if (usecase == NULL) {
1113 ALOGE("%s: Could not find the usecase (%d) in the list",
1114 __func__, in->usecase);
1115 return -EINVAL;
1116 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001117
1118 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1119 if (ret < 0) {
1120 ALOGE("%s Failed to get module id %d", __func__, ret);
1121 return ret;
1122 }
1123 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1124 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1125
1126 if(enable)
1127 param_value = effect_config.param_value;
1128
1129 /*Special handling for AEC & NS effects Param values need to be
1130 updated if module ids are same*/
1131
1132 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1133 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1134 if (ret < 0)
1135 return ret;
1136 }
1137
1138 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1139
1140 return ret;
1141}
1142
1143static void check_and_enable_effect(struct audio_device *adev)
1144{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001145 if(!voice_extn_is_dynamic_ecns_enabled())
1146 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001147
Eric Laurent637e2d42018-11-15 12:24:31 -08001148 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001149
Eric Laurent637e2d42018-11-15 12:24:31 -08001150 if (in != NULL && !in->standby) {
1151 if (in->enable_aec)
1152 enable_disable_effect(adev, EFFECT_AEC, true);
1153
1154 if (in->enable_ns &&
1155 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1156 enable_disable_effect(adev, EFFECT_NS, true);
1157 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001158 }
1159}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001160
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001161int pcm_ioctl(struct pcm *pcm, int request, ...)
1162{
1163 va_list ap;
1164 void * arg;
1165 int pcm_fd = *(int*)pcm;
1166
1167 va_start(ap, request);
1168 arg = va_arg(ap, void *);
1169 va_end(ap);
1170
1171 return ioctl(pcm_fd, request, arg);
1172}
1173
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001174int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001175 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001176{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001177 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001178 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301179 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301180 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001181 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301182 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001183
1184 if (usecase == NULL)
1185 return -EINVAL;
1186
1187 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1188
Carter Hsu2e429db2019-05-14 18:50:52 +08001189 if (usecase->type == PCM_CAPTURE) {
1190 struct stream_in *in = usecase->stream.in;
1191 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001192 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001193
1194 if (in) {
1195 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001196 list_init(&out_devices);
1197 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001198 struct listnode *node;
1199 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1200 USECASE_AUDIO_PLAYBACK_VOIP);
1201 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001202 assign_devices(&out_devices,
1203 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001204 } else if (adev->primary_output &&
1205 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001206 assign_devices(&out_devices,
1207 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001208 } else {
1209 list_for_each(node, &adev->usecase_list) {
1210 uinfo = node_to_item(node, struct audio_usecase, list);
1211 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001212 assign_devices(&out_devices,
1213 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001214 break;
1215 }
1216 }
1217 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001218
1219 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001220 in->ec_opened = true;
1221 }
1222 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001223 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1224 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1225 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001226 snd_device = usecase->in_snd_device;
1227 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001228 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001229 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001230
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001231#ifdef DS1_DOLBY_DAP_ENABLED
1232 audio_extn_dolby_set_dmid(adev);
1233 audio_extn_dolby_set_endpoint(adev);
1234#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001235 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001236 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301237 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001238 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001239 if (audio_extn_is_maxx_audio_enabled())
1240 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301241 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301242 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1243 out = usecase->stream.out;
1244 if (out && out->compr)
1245 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1246 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301247
1248 if (usecase->type == PCM_CAPTURE) {
1249 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001250 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301251 ALOGD("%s: set custom mtmx params v1", __func__);
1252 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1253 }
1254 } else {
1255 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1256 }
Manish Dewangan58229382017-02-02 15:48:41 +05301257
Andy Hung756ecc12018-10-19 17:47:12 -07001258 // we shouldn't truncate mixer_path
1259 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1260 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1261 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001262 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001263 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301264 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1265 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1266 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1267 if (parms) {
1268 audio_extn_fm_set_parameters(adev, parms);
1269 str_parms_destroy(parms);
1270 }
1271 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272 ALOGV("%s: exit", __func__);
1273 return 0;
1274}
1275
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001276int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001277 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001279 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001280 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301281 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001282
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301283 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001284 return -EINVAL;
1285
1286 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301287 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001288 snd_device = usecase->in_snd_device;
1289 else
1290 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001291 // we shouldn't truncate mixer_path
1292 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1293 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1294 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001295 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001296 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001297 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001298 if (usecase->type == PCM_CAPTURE) {
1299 struct stream_in *in = usecase->stream.in;
1300 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001301 struct listnode out_devices;
1302 list_init(&out_devices);
1303 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001304 in->ec_opened = false;
1305 }
1306 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001307 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301308 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301309
1310 if (usecase->type == PCM_CAPTURE) {
1311 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001312 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301313 ALOGD("%s: reset custom mtmx params v1", __func__);
1314 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1315 }
1316 } else {
1317 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1318 }
1319
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001320 if ((usecase->type == PCM_PLAYBACK) &&
1321 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301322 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001324 ALOGV("%s: exit", __func__);
1325 return 0;
1326}
1327
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001328int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001329 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001330{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301331 int i, num_devices = 0;
1332 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001333 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1334
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001335 if (snd_device < SND_DEVICE_MIN ||
1336 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001337 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001338 return -EINVAL;
1339 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001340
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001341 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001342 ALOGE("%s: Invalid sound device returned", __func__);
1343 return -EINVAL;
1344 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001345
1346 adev->snd_dev_ref_cnt[snd_device]++;
1347
1348 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1349 (platform_split_snd_device(adev->platform,
1350 snd_device,
1351 &num_devices,
1352 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001353 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001354 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001355 return 0;
1356 }
1357
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001358 if (audio_extn_spkr_prot_is_enabled())
1359 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001360
Aalique Grahame22e49102018-12-18 14:23:57 -08001361 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1362
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001363 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1364 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001365 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1366 goto err;
1367 }
1368 audio_extn_dev_arbi_acquire(snd_device);
1369 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001370 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001371 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001372 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001373 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001374 } else if (platform_split_snd_device(adev->platform,
1375 snd_device,
1376 &num_devices,
1377 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301378 for (i = 0; i < num_devices; i++) {
1379 enable_snd_device(adev, new_snd_devices[i]);
1380 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001381 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001382 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001383 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301384
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301385
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001386 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1387 (audio_extn_a2dp_start_playback() < 0)) {
1388 ALOGE(" fail to configure A2dp Source control path ");
1389 goto err;
1390 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001391
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001392 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1393 (audio_extn_a2dp_start_capture() < 0)) {
1394 ALOGE(" fail to configure A2dp Sink control path ");
1395 goto err;
1396 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301397
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001398 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1399 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1400 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1401 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1402 ALOGE(" fail to configure sco control path ");
1403 goto err;
1404 }
Zhou Song12c29502019-03-16 10:37:18 +08001405 }
1406
Zhou Song331c8e52019-08-26 14:16:12 +08001407 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001408 /* due to the possibility of calibration overwrite between listen
1409 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001410 audio_extn_sound_trigger_update_device_status(snd_device,
1411 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301412 audio_extn_listen_update_device_status(snd_device,
1413 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001414 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001415 audio_extn_sound_trigger_update_device_status(snd_device,
1416 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301417 audio_extn_listen_update_device_status(snd_device,
1418 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001419 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001420 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001421 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001422 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301423
1424 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1425 !adev->native_playback_enabled &&
1426 audio_is_true_native_stream_active(adev)) {
1427 ALOGD("%s: %d: napb: enabling native mode in hardware",
1428 __func__, __LINE__);
1429 audio_route_apply_and_update_path(adev->audio_route,
1430 "true-native-mode");
1431 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301432 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301433 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1434 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001435 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001436 ALOGD("%s: init ec ref loopback", __func__);
1437 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1438 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001439 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001440 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001441err:
1442 adev->snd_dev_ref_cnt[snd_device]--;
1443 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001444}
1445
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001446int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001447 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001448{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301449 int i, num_devices = 0;
1450 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001451 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1452
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001453 if (snd_device < SND_DEVICE_MIN ||
1454 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001455 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001456 return -EINVAL;
1457 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001458
1459 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1460 ALOGE("%s: Invalid sound device returned", __func__);
1461 return -EINVAL;
1462 }
1463
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001464 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1465 ALOGE("%s: device ref cnt is already 0", __func__);
1466 return -EINVAL;
1467 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001468
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001469 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001470
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001471
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001472 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001473 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301474
Aalique Grahame22e49102018-12-18 14:23:57 -08001475 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1476
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001477 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1478 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001479 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001480
1481 // when speaker device is disabled, reset swap.
1482 // will be renabled on usecase start
1483 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001484 } else if (platform_split_snd_device(adev->platform,
1485 snd_device,
1486 &num_devices,
1487 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301488 for (i = 0; i < num_devices; i++) {
1489 disable_snd_device(adev, new_snd_devices[i]);
1490 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001491 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001492 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001493 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001494 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001495
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001496 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301497 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001498 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001499 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001500 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001501 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301502 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001503 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301504 adev->native_playback_enabled) {
1505 ALOGD("%s: %d: napb: disabling native mode in hardware",
1506 __func__, __LINE__);
1507 audio_route_reset_and_update_path(adev->audio_route,
1508 "true-native-mode");
1509 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001510 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301511 adev->asrc_mode_enabled) {
1512 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301513 disable_asrc_mode(adev);
1514 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001515 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301516 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001517 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001518 ALOGD("%s: deinit ec ref loopback", __func__);
1519 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1520 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001521
1522 audio_extn_utils_release_snd_device(snd_device);
1523 } else {
1524 if (platform_split_snd_device(adev->platform,
1525 snd_device,
1526 &num_devices,
1527 new_snd_devices) == 0) {
1528 for (i = 0; i < num_devices; i++) {
1529 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1530 }
1531 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001532 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 return 0;
1535}
1536
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001537/*
1538 legend:
1539 uc - existing usecase
1540 new_uc - new usecase
1541 d1, d11, d2 - SND_DEVICE enums
1542 a1, a2 - corresponding ANDROID device enums
1543 B1, B2 - backend strings
1544
1545case 1
1546 uc->dev d1 (a1) B1
1547 new_uc->dev d1 (a1), d2 (a2) B1, B2
1548
1549 resolution: disable and enable uc->dev on d1
1550
1551case 2
1552 uc->dev d1 (a1) B1
1553 new_uc->dev d11 (a1) B1
1554
1555 resolution: need to switch uc since d1 and d11 are related
1556 (e.g. speaker and voice-speaker)
1557 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1558
1559case 3
1560 uc->dev d1 (a1) B1
1561 new_uc->dev d2 (a2) B2
1562
1563 resolution: no need to switch uc
1564
1565case 4
1566 uc->dev d1 (a1) B1
1567 new_uc->dev d2 (a2) B1
1568
1569 resolution: disable enable uc-dev on d2 since backends match
1570 we cannot enable two streams on two different devices if they
1571 share the same backend. e.g. if offload is on speaker device using
1572 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1573 using the same backend, offload must also be switched to voice-handset.
1574
1575case 5
1576 uc->dev d1 (a1) B1
1577 new_uc->dev d1 (a1), d2 (a2) B1
1578
1579 resolution: disable enable uc-dev on d2 since backends match
1580 we cannot enable two streams on two different devices if they
1581 share the same backend.
1582
1583case 6
1584 uc->dev d1 (a1) B1
1585 new_uc->dev d2 (a1) B2
1586
1587 resolution: no need to switch
1588
1589case 7
1590 uc->dev d1 (a1), d2 (a2) B1, B2
1591 new_uc->dev d1 (a1) B1
1592
1593 resolution: no need to switch
1594
Zhou Song4ba65882018-07-09 14:48:07 +08001595case 8
1596 uc->dev d1 (a1) B1
1597 new_uc->dev d11 (a1), d2 (a2) B1, B2
1598 resolution: compared to case 1, for this case, d1 and d11 are related
1599 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001600*/
1601static snd_device_t derive_playback_snd_device(void * platform,
1602 struct audio_usecase *uc,
1603 struct audio_usecase *new_uc,
1604 snd_device_t new_snd_device)
1605{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001606 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001607
1608 snd_device_t d1 = uc->out_snd_device;
1609 snd_device_t d2 = new_snd_device;
1610
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001611 list_init(&a1);
1612 list_init(&a2);
1613
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301614 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301615 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001616 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1617 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301618 break;
1619 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001620 assign_devices(&a1, &uc->stream.out->device_list);
1621 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301622 break;
1623 }
1624
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001625 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001626 if (!compare_devices(&a1, &a2) &&
1627 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001628 snd_device_t d3[2];
1629 int num_devices = 0;
1630 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001631 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001632 &num_devices,
1633 d3);
1634 if (ret < 0) {
1635 if (ret != -ENOSYS) {
1636 ALOGW("%s failed to split snd_device %d",
1637 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001638 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001639 }
1640 goto end;
1641 }
1642
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001643 if (platform_check_backends_match(d3[0], d3[1])) {
1644 return d2; // case 5
1645 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001646 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301647 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001648 // check if d1 is related to any of d3's
1649 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001650 return d1; // case 1
1651 else
1652 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001653 }
1654 } else {
1655 if (platform_check_backends_match(d1, d2)) {
1656 return d2; // case 2, 4
1657 } else {
1658 return d1; // case 6, 3
1659 }
1660 }
1661
1662end:
1663 return d2; // return whatever was calculated before.
1664}
1665
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001666static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301667 struct audio_usecase *uc_info,
1668 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001669{
1670 struct listnode *node;
1671 struct audio_usecase *usecase;
1672 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301673 snd_device_t uc_derive_snd_device;
1674 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001675 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1676 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001677 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301678 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001679 /*
1680 * This function is to make sure that all the usecases that are active on
1681 * the hardware codec backend are always routed to any one device that is
1682 * handled by the hardware codec.
1683 * For example, if low-latency and deep-buffer usecases are currently active
1684 * on speaker and out_set_parameters(headset) is received on low-latency
1685 * output, then we have to make sure deep-buffer is also switched to headset,
1686 * because of the limitation that both the devices cannot be enabled
1687 * at the same time as they share the same backend.
1688 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001689 /*
1690 * This call is to check if we need to force routing for a particular stream
1691 * If there is a backend configuration change for the device when a
1692 * new stream starts, then ADM needs to be closed and re-opened with the new
1693 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001694 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001695 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001696 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1697 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301698 /* For a2dp device reconfigure all active sessions
1699 * with new AFE encoder format based on a2dp state
1700 */
1701 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1702 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1703 audio_extn_a2dp_is_force_device_switch()) {
1704 force_routing = true;
1705 force_restart_session = true;
1706 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301707 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1708
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001709 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001710 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001711 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1713 switch_device[i] = false;
1714
1715 list_for_each(node, &adev->usecase_list) {
1716 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001717
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301718 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1719 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301720 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301721 platform_get_snd_device_name(usecase->out_snd_device),
1722 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301723 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1724 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301725 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1726 usecase, uc_info, snd_device);
1727 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001728 (is_codec_backend_out_device_type(&usecase->device_list) ||
1729 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1730 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1731 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1732 is_a2dp_out_device_type(&usecase->device_list) ||
1733 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301734 ((force_restart_session) ||
1735 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301736 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1737 __func__, use_case_table[usecase->id],
1738 platform_get_snd_device_name(usecase->out_snd_device));
1739 disable_audio_route(adev, usecase);
1740 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301741 /* Enable existing usecase on derived playback device */
1742 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301743 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301744 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001745 }
1746 }
1747
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301748 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1749 num_uc_to_switch);
1750
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001751 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001752 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001753
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301754 /* Make sure the previous devices to be disabled first and then enable the
1755 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001756 list_for_each(node, &adev->usecase_list) {
1757 usecase = node_to_item(node, struct audio_usecase, list);
1758 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001759 /* Check if output sound device to be switched can be split and if any
1760 of the split devices match with derived sound device */
1761 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1762 &num_devices, split_snd_devices) == 0) {
1763 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1764 for (i = 0; i < num_devices; i++) {
1765 /* Disable devices that do not match with derived sound device */
1766 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1767 disable_snd_device(adev, split_snd_devices[i]);
1768 }
1769 } else {
1770 disable_snd_device(adev, usecase->out_snd_device);
1771 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001772 }
1773 }
1774
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001775 list_for_each(node, &adev->usecase_list) {
1776 usecase = node_to_item(node, struct audio_usecase, list);
1777 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001778 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1779 &num_devices, split_snd_devices) == 0) {
1780 /* Enable derived sound device only if it does not match with
1781 one of the split sound devices. This is because the matching
1782 sound device was not disabled */
1783 bool should_enable = true;
1784 for (i = 0; i < num_devices; i++) {
1785 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1786 should_enable = false;
1787 break;
1788 }
1789 }
1790 if (should_enable)
1791 enable_snd_device(adev, derive_snd_device[usecase->id]);
1792 } else {
1793 enable_snd_device(adev, derive_snd_device[usecase->id]);
1794 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001795 }
1796 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001797
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001798 /* Re-route all the usecases on the shared backend other than the
1799 specified usecase to new snd devices */
1800 list_for_each(node, &adev->usecase_list) {
1801 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301802 /* Update the out_snd_device only before enabling the audio route */
1803 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301804 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301805 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301806 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301807 use_case_table[usecase->id],
1808 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001809 /* Update voc calibration before enabling VoIP route */
1810 if (usecase->type == VOIP_CALL)
1811 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001812 usecase->out_snd_device,
1813 platform_get_input_snd_device(
1814 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301815 &uc_info->device_list,
1816 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301817 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301818 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001819 out_set_voip_volume(&usecase->stream.out->stream,
1820 usecase->stream.out->volume_l,
1821 usecase->stream.out->volume_r);
1822 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301823 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001824 }
1825 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001826 }
1827}
1828
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301829static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001830 struct audio_usecase *uc_info,
1831 snd_device_t snd_device)
1832{
1833 struct listnode *node;
1834 struct audio_usecase *usecase;
1835 bool switch_device[AUDIO_USECASE_MAX];
1836 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001837 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001838 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001839
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301840 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1841 snd_device);
1842 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301843
1844 /*
1845 * Make sure out devices is checked against out codec backend device and
1846 * also in devices against in codec backend. Checking out device against in
1847 * codec backend or vice versa causes issues.
1848 */
1849 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001850 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001851 /*
1852 * This function is to make sure that all the active capture usecases
1853 * are always routed to the same input sound device.
1854 * For example, if audio-record and voice-call usecases are currently
1855 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1856 * is received for voice call then we have to make sure that audio-record
1857 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1858 * because of the limitation that two devices cannot be enabled
1859 * at the same time if they share the same backend.
1860 */
1861 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1862 switch_device[i] = false;
1863
1864 list_for_each(node, &adev->usecase_list) {
1865 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301866 /*
1867 * TODO: Enhance below condition to handle BT sco/USB multi recording
1868 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301869
1870 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1871 (usecase->in_snd_device != snd_device || force_routing));
1872 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1873 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1874 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001875 ((backend_check_cond &&
1876 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001877 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001878 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001879 is_single_device_type_equal(&usecase->device_list,
1880 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001881 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001882 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001883 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301884 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001885 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001886 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001887 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001888 switch_device[usecase->id] = true;
1889 num_uc_to_switch++;
1890 }
1891 }
1892
1893 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001894 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001895
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301896 /* Make sure the previous devices to be disabled first and then enable the
1897 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001898 list_for_each(node, &adev->usecase_list) {
1899 usecase = node_to_item(node, struct audio_usecase, list);
1900 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001901 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001902 }
1903 }
1904
1905 list_for_each(node, &adev->usecase_list) {
1906 usecase = node_to_item(node, struct audio_usecase, list);
1907 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001908 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001909 }
1910 }
1911
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001912 /* Re-route all the usecases on the shared backend other than the
1913 specified usecase to new snd devices */
1914 list_for_each(node, &adev->usecase_list) {
1915 usecase = node_to_item(node, struct audio_usecase, list);
1916 /* Update the in_snd_device only before enabling the audio route */
1917 if (switch_device[usecase->id] ) {
1918 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001919 if (usecase->type != VOICE_CALL) {
1920 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301921 if (usecase->type == VOIP_CALL) {
1922 snd_device_t voip_snd_device;
1923 voip_snd_device = platform_get_output_snd_device(adev->platform,
1924 uc_info->stream.out,
1925 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08001926 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301927 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08001928 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05301929 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05301930 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001931 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001932 }
1933 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001934 }
1935}
1936
Mingming Yin3a941d42016-02-17 18:08:05 -08001937static void reset_hdmi_sink_caps(struct stream_out *out) {
1938 int i = 0;
1939
1940 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1941 out->supported_channel_masks[i] = 0;
1942 }
1943 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1944 out->supported_formats[i] = 0;
1945 }
1946 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1947 out->supported_sample_rates[i] = 0;
1948 }
1949}
1950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001952static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953{
Mingming Yin3a941d42016-02-17 18:08:05 -08001954 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001955 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
1956 out->extconn.cs.controller,
1957 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958
Mingming Yin3a941d42016-02-17 18:08:05 -08001959 reset_hdmi_sink_caps(out);
1960
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001961 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08001962 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001963 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08001964 out->extconn.cs.stream);
1965 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001966 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001967 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001968 }
1969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001972 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001973 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001974 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1975 case 6:
1976 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1977 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1978 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1979 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1980 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1981 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 break;
1983 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001984 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001985 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986 break;
1987 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001988
1989 // check channel format caps
1990 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001991 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
1992 out->extconn.cs.controller,
1993 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08001994 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1995 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1996 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1997 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1998 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1999 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
2000 }
2001
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002002 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2003 out->extconn.cs.controller,
2004 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002005 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2006 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2007 }
2008
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002009 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2010 out->extconn.cs.controller,
2011 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002012 ALOGV(":%s HDMI supports DTS format", __func__);
2013 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2014 }
2015
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002016 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2017 out->extconn.cs.controller,
2018 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002019 ALOGV(":%s HDMI supports DTS HD format", __func__);
2020 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2021 }
2022
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002023 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2024 out->extconn.cs.controller,
2025 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002026 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2027 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2028 }
2029
Mingming Yin3a941d42016-02-17 18:08:05 -08002030
2031 // check sample rate caps
2032 i = 0;
2033 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002034 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2035 out->extconn.cs.controller,
2036 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002037 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2038 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2039 }
2040 }
2041
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002042 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043}
2044
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002045static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2046 uint32_t *supported_sample_rates __unused,
2047 uint32_t max_rates __unused)
2048{
2049 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2050 supported_sample_rates,
2051 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302052 ssize_t i = 0;
2053
2054 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002055 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2056 supported_sample_rates[i]);
2057 }
2058 return count;
2059}
2060
2061static inline int read_usb_sup_channel_masks(bool is_playback,
2062 audio_channel_mask_t *supported_channel_masks,
2063 uint32_t max_masks)
2064{
2065 int channels = audio_extn_usb_get_max_channels(is_playback);
2066 int channel_count;
2067 uint32_t num_masks = 0;
2068 if (channels > MAX_HIFI_CHANNEL_COUNT)
2069 channels = MAX_HIFI_CHANNEL_COUNT;
2070
2071 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002072 // start from 2 channels as framework currently doesn't support mono.
2073 if (channels >= FCC_2) {
2074 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2075 }
2076 for (channel_count = FCC_2;
2077 channel_count <= channels && num_masks < max_masks;
2078 ++channel_count) {
2079 supported_channel_masks[num_masks++] =
2080 audio_channel_mask_for_index_assignment_from_count(channel_count);
2081 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002082 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002083 // For capture we report all supported channel masks from 1 channel up.
2084 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002085 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2086 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002087 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2088 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2089 if (channel_count <= FCC_2) {
2090 mask = audio_channel_in_mask_from_count(channel_count);
2091 supported_channel_masks[num_masks++] = mask;
2092 }
2093 const audio_channel_mask_t index_mask =
2094 audio_channel_mask_for_index_assignment_from_count(channel_count);
2095 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2096 supported_channel_masks[num_masks++] = index_mask;
2097 }
2098 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002099 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302100
vincenttewf51c94e2019-05-07 10:28:53 +08002101 for (size_t i = 0; i < num_masks; ++i) {
2102 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2103 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302104 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002105 return num_masks;
2106}
2107
2108static inline int read_usb_sup_formats(bool is_playback __unused,
2109 audio_format_t *supported_formats,
2110 uint32_t max_formats __unused)
2111{
2112 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2113 switch (bitwidth) {
2114 case 24:
2115 // XXX : usb.c returns 24 for s24 and s24_le?
2116 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2117 break;
2118 case 32:
2119 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2120 break;
2121 case 16:
2122 default :
2123 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2124 break;
2125 }
2126 ALOGV("%s: %s supported format %d", __func__,
2127 is_playback ? "P" : "C", bitwidth);
2128 return 1;
2129}
2130
2131static inline int read_usb_sup_params_and_compare(bool is_playback,
2132 audio_format_t *format,
2133 audio_format_t *supported_formats,
2134 uint32_t max_formats,
2135 audio_channel_mask_t *mask,
2136 audio_channel_mask_t *supported_channel_masks,
2137 uint32_t max_masks,
2138 uint32_t *rate,
2139 uint32_t *supported_sample_rates,
2140 uint32_t max_rates) {
2141 int ret = 0;
2142 int num_formats;
2143 int num_masks;
2144 int num_rates;
2145 int i;
2146
2147 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2148 max_formats);
2149 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2150 max_masks);
2151
2152 num_rates = read_usb_sup_sample_rates(is_playback,
2153 supported_sample_rates, max_rates);
2154
2155#define LUT(table, len, what, dflt) \
2156 for (i=0; i<len && (table[i] != what); i++); \
2157 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2158
2159 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2160 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2161 LUT(supported_sample_rates, num_rates, *rate, 0);
2162
2163#undef LUT
2164 return ret < 0 ? -EINVAL : 0; // HACK TBD
2165}
2166
Alexy Josephb1379942016-01-29 15:49:38 -08002167audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002168 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002169{
2170 struct audio_usecase *usecase;
2171 struct listnode *node;
2172
2173 list_for_each(node, &adev->usecase_list) {
2174 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002175 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002176 ALOGV("%s: usecase id %d", __func__, usecase->id);
2177 return usecase->id;
2178 }
2179 }
2180 return USECASE_INVALID;
2181}
2182
Alexy Josephb1379942016-01-29 15:49:38 -08002183struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002184 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002185{
2186 struct audio_usecase *usecase;
2187 struct listnode *node;
2188
2189 list_for_each(node, &adev->usecase_list) {
2190 usecase = node_to_item(node, struct audio_usecase, list);
2191 if (usecase->id == uc_id)
2192 return usecase;
2193 }
2194 return NULL;
2195}
2196
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302197/*
2198 * is a true native playback active
2199 */
2200bool audio_is_true_native_stream_active(struct audio_device *adev)
2201{
2202 bool active = false;
2203 int i = 0;
2204 struct listnode *node;
2205
2206 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2207 ALOGV("%s:napb: not in true mode or non hdphones device",
2208 __func__);
2209 active = false;
2210 goto exit;
2211 }
2212
2213 list_for_each(node, &adev->usecase_list) {
2214 struct audio_usecase *uc;
2215 uc = node_to_item(node, struct audio_usecase, list);
2216 struct stream_out *curr_out =
2217 (struct stream_out*) uc->stream.out;
2218
2219 if (curr_out && PCM_PLAYBACK == uc->type) {
2220 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2221 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2222 uc->id, curr_out->sample_rate,
2223 curr_out->bit_width,
2224 platform_get_snd_device_name(uc->out_snd_device));
2225
2226 if (is_offload_usecase(uc->id) &&
2227 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2228 active = true;
2229 ALOGD("%s:napb:native stream detected", __func__);
2230 }
2231 }
2232 }
2233exit:
2234 return active;
2235}
2236
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002237uint32_t adev_get_dsp_bit_width_enforce_mode()
2238{
2239 if (adev == NULL) {
2240 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2241 return 0;
2242 }
2243 return adev->dsp_bit_width_enforce_mode;
2244}
2245
2246static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2247{
2248 char value[PROPERTY_VALUE_MAX];
2249 int trial;
2250 uint32_t dsp_bit_width_enforce_mode = 0;
2251
2252 if (!mixer) {
2253 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2254 __func__);
2255 return 0;
2256 }
2257
2258 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2259 value, NULL) > 0) {
2260 trial = atoi(value);
2261 switch (trial) {
2262 case 16:
2263 dsp_bit_width_enforce_mode = 16;
2264 break;
2265 case 24:
2266 dsp_bit_width_enforce_mode = 24;
2267 break;
2268 case 32:
2269 dsp_bit_width_enforce_mode = 32;
2270 break;
2271 default:
2272 dsp_bit_width_enforce_mode = 0;
2273 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2274 break;
2275 }
2276 }
2277
2278 return dsp_bit_width_enforce_mode;
2279}
2280
2281static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2282 uint32_t enforce_mode,
2283 bool enable)
2284{
2285 struct mixer_ctl *ctl = NULL;
2286 const char *mixer_ctl_name = "ASM Bit Width";
2287 uint32_t asm_bit_width_mode = 0;
2288
2289 if (enforce_mode == 0) {
2290 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2291 return;
2292 }
2293
2294 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2295 if (!ctl) {
2296 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2297 __func__, mixer_ctl_name);
2298 return;
2299 }
2300
2301 if (enable)
2302 asm_bit_width_mode = enforce_mode;
2303 else
2304 asm_bit_width_mode = 0;
2305
2306 ALOGV("%s DSP bit width feature status is %d width=%d",
2307 __func__, enable, asm_bit_width_mode);
2308 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2309 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2310 asm_bit_width_mode);
2311
2312 return;
2313}
2314
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302315/*
2316 * if native DSD playback active
2317 */
2318bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2319{
2320 bool active = false;
2321 struct listnode *node = NULL;
2322 struct audio_usecase *uc = NULL;
2323 struct stream_out *curr_out = NULL;
2324
2325 list_for_each(node, &adev->usecase_list) {
2326 uc = node_to_item(node, struct audio_usecase, list);
2327 curr_out = (struct stream_out*) uc->stream.out;
2328
2329 if (curr_out && PCM_PLAYBACK == uc->type &&
2330 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2331 active = true;
2332 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302333 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302334 }
2335 }
2336 return active;
2337}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302338
2339static bool force_device_switch(struct audio_usecase *usecase)
2340{
2341 bool ret = false;
2342 bool is_it_true_mode = false;
2343
Zhou Song30f2c3e2018-02-08 14:02:15 +08002344 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302345 usecase->type == TRANSCODE_LOOPBACK_RX ||
2346 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002347 return false;
2348 }
2349
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002350 if(usecase->stream.out == NULL) {
2351 ALOGE("%s: stream.out is NULL", __func__);
2352 return false;
2353 }
2354
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302355 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002356 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002357 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2358 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302359 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2360 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2361 (!is_it_true_mode && adev->native_playback_enabled)){
2362 ret = true;
2363 ALOGD("napb: time to toggle native mode");
2364 }
2365 }
2366
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302367 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302368 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2369 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002370 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302371 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302372 ALOGD("Force a2dp device switch to update new encoder config");
2373 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002374 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302375
Florian Pfister1a84f312018-07-19 14:38:18 +02002376 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302377 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2378 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002379 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302380 return ret;
2381}
2382
Aalique Grahame22e49102018-12-18 14:23:57 -08002383static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2384{
2385 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2386}
2387
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302388bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2389{
2390 bool ret=false;
2391 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002392 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2393 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302394 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2395 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002396 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302397 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
Mingshu Pang16093502020-04-20 11:21:16 +08002398 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC ||
2399 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC)
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302400 ret = true;
2401
2402 return ret;
2403}
2404
2405bool is_a2dp_device(snd_device_t out_snd_device)
2406{
2407 bool ret=false;
2408 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2409 ret = true;
2410
2411 return ret;
2412}
2413
2414bool is_bt_soc_on(struct audio_device *adev)
2415{
2416 struct mixer_ctl *ctl;
2417 char *mixer_ctl_name = "BT SOC status";
2418 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2419 bool bt_soc_status = true;
2420 if (!ctl) {
2421 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2422 __func__, mixer_ctl_name);
2423 /*This is to ensure we dont break targets which dont have the kernel change*/
2424 return true;
2425 }
2426 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2427 ALOGD("BT SOC status: %d",bt_soc_status);
2428 return bt_soc_status;
2429}
2430
Zhou Song331c8e52019-08-26 14:16:12 +08002431static int configure_btsco_sample_rate(snd_device_t snd_device)
2432{
2433 struct mixer_ctl *ctl = NULL;
2434 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2435 char *rate_str = NULL;
2436 bool is_rx_dev = true;
2437
2438 if (is_btsco_device(snd_device, snd_device)) {
2439 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2440 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2441 if (!ctl_sr_tx || !ctl_sr_rx) {
2442 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2443 if (!ctl_sr)
2444 return -ENOSYS;
2445 }
2446
2447 switch (snd_device) {
2448 case SND_DEVICE_OUT_BT_SCO:
2449 rate_str = "KHZ_8";
2450 break;
2451 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2452 case SND_DEVICE_IN_BT_SCO_MIC:
2453 rate_str = "KHZ_8";
2454 is_rx_dev = false;
2455 break;
2456 case SND_DEVICE_OUT_BT_SCO_WB:
2457 rate_str = "KHZ_16";
2458 break;
2459 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2460 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2461 rate_str = "KHZ_16";
2462 is_rx_dev = false;
2463 break;
2464 default:
2465 return 0;
2466 }
2467
2468 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2469 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2470 return -ENOSYS;
2471 }
2472 return 0;
2473}
2474
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302475int out_standby_l(struct audio_stream *stream);
2476
Eric Laurent637e2d42018-11-15 12:24:31 -08002477struct stream_in *adev_get_active_input(const struct audio_device *adev)
2478{
2479 struct listnode *node;
2480 struct stream_in *last_active_in = NULL;
2481
2482 /* Get last added active input.
2483 * TODO: We may use a priority mechanism to pick highest priority active source */
2484 list_for_each(node, &adev->usecase_list)
2485 {
2486 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2487 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2488 last_active_in = usecase->stream.in;
2489 }
2490
2491 return last_active_in;
2492}
2493
2494struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2495{
2496 struct listnode *node;
2497
2498 /* First check active inputs with voice communication source and then
2499 * any input if audio mode is in communication */
2500 list_for_each(node, &adev->usecase_list)
2501 {
2502 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2503 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2504 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2505 return usecase->stream.in;
2506 }
2507 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2508 return adev_get_active_input(adev);
2509
2510 return NULL;
2511}
2512
Carter Hsu2e429db2019-05-14 18:50:52 +08002513/*
2514 * Aligned with policy.h
2515 */
2516static inline int source_priority(int inputSource)
2517{
2518 switch (inputSource) {
2519 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2520 return 9;
2521 case AUDIO_SOURCE_CAMCORDER:
2522 return 8;
2523 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2524 return 7;
2525 case AUDIO_SOURCE_UNPROCESSED:
2526 return 6;
2527 case AUDIO_SOURCE_MIC:
2528 return 5;
2529 case AUDIO_SOURCE_ECHO_REFERENCE:
2530 return 4;
2531 case AUDIO_SOURCE_FM_TUNER:
2532 return 3;
2533 case AUDIO_SOURCE_VOICE_RECOGNITION:
2534 return 2;
2535 case AUDIO_SOURCE_HOTWORD:
2536 return 1;
2537 default:
2538 break;
2539 }
2540 return 0;
2541}
2542
2543static struct stream_in *get_priority_input(struct audio_device *adev)
2544{
2545 struct listnode *node;
2546 struct audio_usecase *usecase;
2547 int last_priority = 0, priority;
2548 struct stream_in *priority_in = NULL;
2549 struct stream_in *in;
2550
2551 list_for_each(node, &adev->usecase_list) {
2552 usecase = node_to_item(node, struct audio_usecase, list);
2553 if (usecase->type == PCM_CAPTURE) {
2554 in = usecase->stream.in;
2555 if (!in)
2556 continue;
2557 priority = source_priority(in->source);
2558
2559 if (priority > last_priority) {
2560 last_priority = priority;
2561 priority_in = in;
2562 }
2563 }
2564 }
2565 return priority_in;
2566}
2567
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002568int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002570 snd_device_t out_snd_device = SND_DEVICE_NONE;
2571 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002572 struct audio_usecase *usecase = NULL;
2573 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002574 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002575 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302576 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002577 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002578 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302580 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2581
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002582 usecase = get_usecase_from_list(adev, uc_id);
2583 if (usecase == NULL) {
2584 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2585 return -EINVAL;
2586 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002588 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002589 (usecase->type == VOIP_CALL) ||
2590 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302591 if(usecase->stream.out == NULL) {
2592 ALOGE("%s: stream.out is NULL", __func__);
2593 return -EINVAL;
2594 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002595 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002596 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2597 uc_id);
2598 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2599 uc_id);
2600 } else {
2601 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302602 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002603 in_snd_device = platform_get_input_snd_device(adev->platform,
2604 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302605 &usecase->stream.out->device_list,
2606 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002607 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002608 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302609 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302610 if (usecase->stream.inout == NULL) {
2611 ALOGE("%s: stream.inout is NULL", __func__);
2612 return -EINVAL;
2613 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002614 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302615 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2616 stream_out.format = usecase->stream.inout->out_config.format;
2617 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302618 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002619 assign_devices(&usecase->device_list,
2620 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302621 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2622 if (usecase->stream.inout == NULL) {
2623 ALOGE("%s: stream.inout is NULL", __func__);
2624 return -EINVAL;
2625 }
Manisha Agarwal03297972020-04-17 15:36:55 +05302626 struct listnode out_devices;
2627 list_init(&out_devices);
2628 in_snd_device = platform_get_input_snd_device(adev->platform, NULL,
2629 &out_devices, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002630 assign_devices(&usecase->device_list,
2631 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002632 } else {
2633 /*
2634 * If the voice call is active, use the sound devices of voice call usecase
2635 * so that it would not result any device switch. All the usecases will
2636 * be switched to new device when select_devices() is called for voice call
2637 * usecase. This is to avoid switching devices for voice call when
2638 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002639 * choose voice call device only if the use case device is
2640 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002641 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002642 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002643 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002644 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002645 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2646 is_codec_backend_out_device_type(&usecase->device_list)) ||
2647 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2648 is_codec_backend_in_device_type(&usecase->device_list)) ||
2649 is_single_device_type_equal(&vc_usecase->device_list,
2650 AUDIO_DEVICE_OUT_HEARING_AID) ||
2651 is_single_device_type_equal(&usecase->device_list,
Robert Lee8a6aaf32019-09-20 16:40:19 +08002652 AUDIO_DEVICE_IN_VOICE_CALL) ||
2653 (is_single_device_type_equal(&usecase->device_list,
2654 AUDIO_DEVICE_IN_USB_HEADSET) &&
2655 is_single_device_type_equal(&vc_usecase->device_list,
2656 AUDIO_DEVICE_OUT_USB_HEADSET)))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002657 in_snd_device = vc_usecase->in_snd_device;
2658 out_snd_device = vc_usecase->out_snd_device;
2659 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002660 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002661 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002662 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002663 if ((voip_usecase != NULL) &&
2664 (usecase->type == PCM_PLAYBACK) &&
2665 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002666 out_snd_device_backend_match = platform_check_backends_match(
2667 voip_usecase->out_snd_device,
2668 platform_get_output_snd_device(
2669 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302670 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002671 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002672 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2673 (is_codec_backend_out_device_type(&usecase->device_list) ||
2674 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002675 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002676 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002677 in_snd_device = voip_usecase->in_snd_device;
2678 out_snd_device = voip_usecase->out_snd_device;
2679 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002680 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002681 hfp_ucid = audio_extn_hfp_get_usecase();
2682 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002683 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002684 in_snd_device = hfp_usecase->in_snd_device;
2685 out_snd_device = hfp_usecase->out_snd_device;
2686 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002687 }
2688 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302689 if (usecase->stream.out == NULL) {
2690 ALOGE("%s: stream.out is NULL", __func__);
2691 return -EINVAL;
2692 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002693 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002694 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002695 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002696 struct stream_out *voip_out = adev->primary_output;
2697 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002698 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002699 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2700 else
2701 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302702 usecase->stream.out,
2703 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002704 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002705
Eric Laurent637e2d42018-11-15 12:24:31 -08002706 if (voip_usecase)
2707 voip_out = voip_usecase->stream.out;
2708
2709 if (usecase->stream.out == voip_out && voip_in != NULL)
2710 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002711 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002712 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302713 if (usecase->stream.in == NULL) {
2714 ALOGE("%s: stream.in is NULL", __func__);
2715 return -EINVAL;
2716 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002717 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002718 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002719 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002720 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002721 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002722 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002723
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002724 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002725 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002726 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2727 USECASE_AUDIO_PLAYBACK_VOIP);
2728
Carter Hsu2e429db2019-05-14 18:50:52 +08002729 usecase->stream.in->enable_ec_port = false;
2730
Eric Laurent637e2d42018-11-15 12:24:31 -08002731 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002732 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002733 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002734 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002735 } else if (adev->primary_output &&
2736 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002737 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002738 } else {
2739 /* forcing speaker o/p device to get matching i/p pair
2740 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002741 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002742 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002743 priority_in = voip_in;
2744 } else {
2745 /* get the input with the highest priority source*/
2746 priority_in = get_priority_input(adev);
2747
2748 if (!priority_in)
2749 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002750 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002751
Eric Laurent637e2d42018-11-15 12:24:31 -08002752 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002753 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302754 &out_devices,
2755 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002756 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002757 }
2758 }
2759
2760 if (out_snd_device == usecase->out_snd_device &&
2761 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302762
2763 if (!force_device_switch(usecase))
2764 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 }
2766
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002767 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002768 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002769 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002770 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2771 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302772 }
2773
Aalique Grahame22e49102018-12-18 14:23:57 -08002774 if (out_snd_device != SND_DEVICE_NONE &&
2775 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2776 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2777 __func__,
2778 use_case_table[uc_id],
2779 adev->last_logged_snd_device[uc_id][0],
2780 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2781 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2782 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2783 -1,
2784 out_snd_device,
2785 platform_get_snd_device_name(out_snd_device),
2786 platform_get_snd_device_acdb_id(out_snd_device));
2787 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2788 }
2789 if (in_snd_device != SND_DEVICE_NONE &&
2790 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2791 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2792 __func__,
2793 use_case_table[uc_id],
2794 adev->last_logged_snd_device[uc_id][1],
2795 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2796 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2797 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2798 -1,
2799 in_snd_device,
2800 platform_get_snd_device_name(in_snd_device),
2801 platform_get_snd_device_acdb_id(in_snd_device));
2802 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2803 }
2804
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 /*
2807 * Limitation: While in call, to do a device switch we need to disable
2808 * and enable both RX and TX devices though one of them is same as current
2809 * device.
2810 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002811 if ((usecase->type == VOICE_CALL) &&
2812 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2813 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002814 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002815 }
2816
2817 if (((usecase->type == VOICE_CALL) ||
2818 (usecase->type == VOIP_CALL)) &&
2819 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2820 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302821 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002822 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002823 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002824
2825 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302826 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002827 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002828 }
2829
Aalique Grahame22e49102018-12-18 14:23:57 -08002830 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2831 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002832 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302833 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002834 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2835 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2836 else
2837 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302838 }
2839
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002840 /* Disable current sound devices */
2841 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002842 disable_audio_route(adev, usecase);
2843 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844 }
2845
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002846 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002847 disable_audio_route(adev, usecase);
2848 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 }
2850
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002851 /* Applicable only on the targets that has external modem.
2852 * New device information should be sent to modem before enabling
2853 * the devices to reduce in-call device switch time.
2854 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002855 if ((usecase->type == VOICE_CALL) &&
2856 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2857 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002858 status = platform_switch_voice_call_enable_device_config(adev->platform,
2859 out_snd_device,
2860 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002861 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002862
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002863 /* Enable new sound devices */
2864 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002865 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302866 if (platform_check_codec_asrc_support(adev->platform))
2867 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002868 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002869 }
2870
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002871 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302872 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002873 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002874 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002875
Avinash Vaish71a8b972014-07-24 15:36:33 +05302876 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002877 status = platform_switch_voice_call_device_post(adev->platform,
2878 out_snd_device,
2879 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302880 enable_audio_route_for_voice_usecases(adev, usecase);
2881 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002882
sangwoo170731f2013-06-08 15:36:36 +09002883 usecase->in_snd_device = in_snd_device;
2884 usecase->out_snd_device = out_snd_device;
2885
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302886 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2887 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302888 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002889 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002890 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002891 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2892 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2893 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2894 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2895 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2896 /*
2897 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2898 * configured device sample rate, if not update the COPP rate to be equal to the
2899 * device sample rate, else open COPP at stream sample rate
2900 */
2901 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2902 usecase->stream.out->sample_rate,
2903 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302904 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302905 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2906 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302907 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002908 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2909 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2910 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2911 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002912 }
2913 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002914
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002915 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002916
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002917 /* If input stream is already running then effect needs to be
2918 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002919 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002920 check_and_enable_effect(adev);
2921
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002922 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002923 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302924 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002925 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2926
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002927 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302928 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002929 voice_extn_compress_voip_is_started(adev))
2930 voice_set_sidetone(adev, out_snd_device, true);
2931 }
2932
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002933 /* Applicable only on the targets that has external modem.
2934 * Enable device command should be sent to modem only after
2935 * enabling voice call mixer controls
2936 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002937 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002938 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2939 out_snd_device,
2940 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302941
2942 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002943 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302944 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002945 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302946 if (is_bt_soc_on(adev) == false){
2947 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002948 if (in->pcm != NULL)
2949 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302950 }
2951 }
2952 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2953 && usecase->stream.out->started) {
2954 if (is_bt_soc_on(adev) == false) {
2955 ALOGD("BT SCO/A2DP disconnected while in connection");
2956 out_standby_l(&usecase->stream.out->stream.common);
2957 }
2958 }
2959 } else if ((usecase->stream.out != NULL) &&
2960 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302961 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2962 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08002963 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302964 usecase->stream.out->started) {
2965 if (is_bt_soc_on(adev) == false) {
2966 ALOGD("BT SCO/A2dp disconnected while in connection");
2967 out_standby_l(&usecase->stream.out->stream.common);
2968 }
2969 }
2970 }
2971
Yung Ti Su70cb8242018-06-22 17:38:47 +08002972 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002973 struct stream_out *voip_out = voip_usecase->stream.out;
2974 audio_extn_utils_send_app_type_gain(adev,
2975 voip_out->app_type_cfg.app_type,
2976 &voip_out->app_type_cfg.gain[0]);
2977 }
2978
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302979 ALOGD("%s: done",__func__);
2980
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981 return status;
2982}
2983
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984static int stop_input_stream(struct stream_in *in)
2985{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302986 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302988
2989 if (in == NULL) {
2990 ALOGE("%s: stream_in ptr is NULL", __func__);
2991 return -EINVAL;
2992 }
2993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002995 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996
Eric Laurent994a6932013-07-17 11:51:42 -07002997 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002998 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 uc_info = get_usecase_from_list(adev, in->usecase);
3000 if (uc_info == NULL) {
3001 ALOGE("%s: Could not find the usecase (%d) in the list",
3002 __func__, in->usecase);
3003 return -EINVAL;
3004 }
3005
Carter Hsu2e429db2019-05-14 18:50:52 +08003006 priority_in = get_priority_input(adev);
3007
Derek Chenea197282019-01-07 17:35:01 -08003008 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3009 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003010
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003011 /* Close in-call recording streams */
3012 voice_check_and_stop_incall_rec_usecase(adev, in);
3013
Eric Laurent150dbfe2013-02-27 14:31:02 -08003014 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003015 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003016
3017 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003018 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003020 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303021 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3022
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003023 list_remove(&uc_info->list);
3024 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025
Carter Hsu2e429db2019-05-14 18:50:52 +08003026 if (priority_in == in) {
3027 priority_in = get_priority_input(adev);
3028 if (priority_in)
3029 select_devices(adev, priority_in->usecase);
3030 }
3031
Vatsal Buchac09ae062018-11-14 13:25:08 +05303032 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003033 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 return ret;
3035}
3036
3037int start_input_stream(struct stream_in *in)
3038{
3039 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003040 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303042
3043 if (in == NULL) {
3044 ALOGE("%s: stream_in ptr is NULL", __func__);
3045 return -EINVAL;
3046 }
3047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003049 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003050 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051
Mingming Yin2664a5b2015-09-03 10:53:11 -07003052 if (get_usecase_from_list(adev, usecase) == NULL)
3053 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303054 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3055 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003056
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303057 if (CARD_STATUS_OFFLINE == in->card_status||
3058 CARD_STATUS_OFFLINE == adev->card_status) {
3059 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303060 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303061 goto error_config;
3062 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303063
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003064 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303065 if (!adev->bt_sco_on) {
3066 ALOGE("%s: SCO profile is not ready, return error", __func__);
3067 ret = -EIO;
3068 goto error_config;
3069 }
3070 }
3071
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003072 /* Check if source matches incall recording usecase criteria */
3073 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3074 if (ret)
3075 goto error_config;
3076 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003077 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3078
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303079 if (audio_extn_cin_attached_usecase(in))
3080 audio_extn_cin_acquire_usecase(in);
3081
Mingming Yin2664a5b2015-09-03 10:53:11 -07003082 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3083 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3084 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003085 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003086 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003087
Eric Laurentb23d5282013-05-14 15:27:20 -07003088 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 if (in->pcm_device_id < 0) {
3090 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3091 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003092 ret = -EINVAL;
3093 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003097
3098 if (!uc_info) {
3099 ret = -ENOMEM;
3100 goto error_config;
3101 }
3102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103 uc_info->id = in->usecase;
3104 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003105 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003106 list_init(&uc_info->device_list);
3107 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003108 uc_info->in_snd_device = SND_DEVICE_NONE;
3109 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003111 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003112 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303113 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3114 adev->perf_lock_opts,
3115 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003116 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117
Derek Chenea197282019-01-07 17:35:01 -08003118 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3119 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003120
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303121 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3122
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303123 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303124 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303125 if (ret)
3126 goto error_open;
3127 else
3128 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003129 }
3130
Haynes Mathew George16081042017-05-31 17:16:49 -07003131 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003132 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003133 ALOGE("%s: pcm stream not ready", __func__);
3134 goto error_open;
3135 }
3136 ret = pcm_start(in->pcm);
3137 if (ret < 0) {
3138 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3139 goto error_open;
3140 }
3141 } else {
3142 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3143 unsigned int pcm_open_retry_count = 0;
3144
3145 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
3146 flags |= PCM_MMAP | PCM_NOIRQ;
3147 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3148 } else if (in->realtime) {
3149 flags |= PCM_MMAP | PCM_NOIRQ;
3150 }
3151
Garmond Leunge2433c32017-09-28 21:51:22 -07003152 if (audio_extn_ffv_get_stream() == in) {
3153 ALOGD("%s: ffv stream, update pcm config", __func__);
3154 audio_extn_ffv_update_pcm_config(&config);
3155 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003156 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3157 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3158
3159 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003160 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003161 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003162 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003163 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303164 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303165 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3166 adev->card_status = CARD_STATUS_OFFLINE;
3167 in->card_status = CARD_STATUS_OFFLINE;
3168 ret = -EIO;
3169 goto error_open;
3170 }
3171
Haynes Mathew George16081042017-05-31 17:16:49 -07003172 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3173 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3174 if (in->pcm != NULL) {
3175 pcm_close(in->pcm);
3176 in->pcm = NULL;
3177 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003178 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003179 ret = -EIO;
3180 goto error_open;
3181 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003182 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003183 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3184 continue;
3185 }
3186 break;
3187 }
3188
3189 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003190 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003191 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003192 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003193 if (ret < 0) {
3194 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3195 pcm_close(in->pcm);
3196 in->pcm = NULL;
3197 goto error_open;
3198 }
3199 register_in_stream(in);
3200 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003201 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003202 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003203 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003204 if (ret < 0) {
3205 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003206 pcm_close(in->pcm);
3207 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003208 goto error_open;
3209 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003210 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003211 }
3212
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003213 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003214 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3215 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003216
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003217 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303218 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3219
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303220done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003221 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303222 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003223 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303224 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003225 return ret;
3226
3227error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003228 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303229 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003231
Eric Laurentc8400632013-02-14 19:04:54 -08003232error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303233 /*
3234 * sleep 50ms to allow sufficient time for kernel
3235 * drivers to recover incases like SSR.
3236 */
3237 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003238 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303239 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003240 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241}
3242
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003243void lock_input_stream(struct stream_in *in)
3244{
3245 pthread_mutex_lock(&in->pre_lock);
3246 pthread_mutex_lock(&in->lock);
3247 pthread_mutex_unlock(&in->pre_lock);
3248}
3249
3250void lock_output_stream(struct stream_out *out)
3251{
3252 pthread_mutex_lock(&out->pre_lock);
3253 pthread_mutex_lock(&out->lock);
3254 pthread_mutex_unlock(&out->pre_lock);
3255}
3256
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003257/* must be called with out->lock locked */
3258static int send_offload_cmd_l(struct stream_out* out, int command)
3259{
3260 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3261
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003262 if (!cmd) {
3263 ALOGE("failed to allocate mem for command 0x%x", command);
3264 return -ENOMEM;
3265 }
3266
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003267 ALOGVV("%s %d", __func__, command);
3268
3269 cmd->cmd = command;
3270 list_add_tail(&out->offload_cmd_list, &cmd->node);
3271 pthread_cond_signal(&out->offload_cond);
3272 return 0;
3273}
3274
3275/* must be called iwth out->lock locked */
3276static void stop_compressed_output_l(struct stream_out *out)
3277{
3278 out->offload_state = OFFLOAD_STATE_IDLE;
3279 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003280 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003281 if (out->compr != NULL) {
3282 compress_stop(out->compr);
3283 while (out->offload_thread_blocked) {
3284 pthread_cond_wait(&out->cond, &out->lock);
3285 }
3286 }
3287}
3288
Varun Balaraje49253e2017-07-06 19:48:56 +05303289bool is_interactive_usecase(audio_usecase_t uc_id)
3290{
3291 unsigned int i;
3292 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3293 if (uc_id == interactive_usecases[i])
3294 return true;
3295 }
3296 return false;
3297}
3298
3299static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3300{
3301 audio_usecase_t ret_uc = USECASE_INVALID;
3302 unsigned int intract_uc_index;
3303 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3304
3305 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3306 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3307 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3308 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3309 ret_uc = interactive_usecases[intract_uc_index];
3310 break;
3311 }
3312 }
3313
3314 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3315 return ret_uc;
3316}
3317
3318static void free_interactive_usecase(struct audio_device *adev,
3319 audio_usecase_t uc_id)
3320{
3321 unsigned int interact_uc_index;
3322 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3323
3324 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3325 if (interactive_usecases[interact_uc_index] == uc_id) {
3326 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3327 break;
3328 }
3329 }
3330 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3331}
3332
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003333bool is_offload_usecase(audio_usecase_t uc_id)
3334{
3335 unsigned int i;
3336 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3337 if (uc_id == offload_usecases[i])
3338 return true;
3339 }
3340 return false;
3341}
3342
Dhananjay Kumarac341582017-02-23 23:42:25 +05303343static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003344{
vivek mehta446c3962015-09-14 10:57:35 -07003345 audio_usecase_t ret_uc = USECASE_INVALID;
3346 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003347 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003348 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303349 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003350 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3351 else
3352 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003353
vivek mehta446c3962015-09-14 10:57:35 -07003354 pthread_mutex_lock(&adev->lock);
3355 if (get_usecase_from_list(adev, ret_uc) != NULL)
3356 ret_uc = USECASE_INVALID;
3357 pthread_mutex_unlock(&adev->lock);
3358
3359 return ret_uc;
3360 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003361
3362 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003363 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3364 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3365 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3366 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003367 break;
3368 }
3369 }
vivek mehta446c3962015-09-14 10:57:35 -07003370
3371 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3372 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003373}
3374
3375static void free_offload_usecase(struct audio_device *adev,
3376 audio_usecase_t uc_id)
3377{
vivek mehta446c3962015-09-14 10:57:35 -07003378 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003379 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003380
3381 if (!adev->multi_offload_enable)
3382 return;
3383
3384 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3385 if (offload_usecases[offload_uc_index] == uc_id) {
3386 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003387 break;
3388 }
3389 }
3390 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3391}
3392
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003393static void *offload_thread_loop(void *context)
3394{
3395 struct stream_out *out = (struct stream_out *) context;
3396 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003397 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003398
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003399 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003400 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003401 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3402
3403 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003404 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003405 out->offload_state = OFFLOAD_STATE_IDLE;
3406 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003407 for (;;) {
3408 struct offload_cmd *cmd = NULL;
3409 stream_callback_event_t event;
3410 bool send_callback = false;
3411
3412 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3413 __func__, list_empty(&out->offload_cmd_list),
3414 out->offload_state);
3415 if (list_empty(&out->offload_cmd_list)) {
3416 ALOGV("%s SLEEPING", __func__);
3417 pthread_cond_wait(&out->offload_cond, &out->lock);
3418 ALOGV("%s RUNNING", __func__);
3419 continue;
3420 }
3421
3422 item = list_head(&out->offload_cmd_list);
3423 cmd = node_to_item(item, struct offload_cmd, node);
3424 list_remove(item);
3425
3426 ALOGVV("%s STATE %d CMD %d out->compr %p",
3427 __func__, out->offload_state, cmd->cmd, out->compr);
3428
3429 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3430 free(cmd);
3431 break;
3432 }
3433
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003434 // allow OFFLOAD_CMD_ERROR reporting during standby
3435 // this is needed to handle failures during compress_open
3436 // Note however that on a pause timeout, the stream is closed
3437 // and no offload usecase will be active. Therefore this
3438 // special case is needed for compress_open failures alone
3439 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3440 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003441 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003442 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003443 pthread_cond_signal(&out->cond);
3444 continue;
3445 }
3446 out->offload_thread_blocked = true;
3447 pthread_mutex_unlock(&out->lock);
3448 send_callback = false;
3449 switch(cmd->cmd) {
3450 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003451 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003452 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003453 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003454 send_callback = true;
3455 event = STREAM_CBK_EVENT_WRITE_READY;
3456 break;
3457 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003458 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303459 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003460 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303461 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003462 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303463 if (ret < 0)
3464 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303465 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303466 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003467 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003468 else
3469 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003470 if (-ENETRESET != ret && !(-EINTR == ret &&
3471 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303472 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303473 pthread_mutex_lock(&out->lock);
3474 out->send_new_metadata = 1;
3475 out->send_next_track_params = true;
3476 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303477 event = STREAM_CBK_EVENT_DRAIN_READY;
3478 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3479 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303480 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003481 break;
3482 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003483 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003484 ret = compress_drain(out->compr);
3485 ALOGD("copl(%p):out of compress_drain", out);
3486 // EINTR check avoids drain interruption due to SSR
3487 if (-ENETRESET != ret && !(-EINTR == ret &&
3488 CARD_STATUS_OFFLINE == out->card_status)) {
3489 send_callback = true;
3490 event = STREAM_CBK_EVENT_DRAIN_READY;
3491 } else
3492 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003493 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303494 case OFFLOAD_CMD_ERROR:
3495 ALOGD("copl(%p): sending error callback to AF", out);
3496 send_callback = true;
3497 event = STREAM_CBK_EVENT_ERROR;
3498 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003499 default:
3500 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3501 break;
3502 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003503 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003504 out->offload_thread_blocked = false;
3505 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003506 if (send_callback && out->client_callback) {
3507 ALOGVV("%s: sending client_callback event %d", __func__, event);
3508 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003509 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003510 free(cmd);
3511 }
3512
3513 pthread_cond_signal(&out->cond);
3514 while (!list_empty(&out->offload_cmd_list)) {
3515 item = list_head(&out->offload_cmd_list);
3516 list_remove(item);
3517 free(node_to_item(item, struct offload_cmd, node));
3518 }
3519 pthread_mutex_unlock(&out->lock);
3520
3521 return NULL;
3522}
3523
3524static int create_offload_callback_thread(struct stream_out *out)
3525{
3526 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3527 list_init(&out->offload_cmd_list);
3528 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3529 offload_thread_loop, out);
3530 return 0;
3531}
3532
3533static int destroy_offload_callback_thread(struct stream_out *out)
3534{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003535 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003536 stop_compressed_output_l(out);
3537 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3538
3539 pthread_mutex_unlock(&out->lock);
3540 pthread_join(out->offload_thread, (void **) NULL);
3541 pthread_cond_destroy(&out->offload_cond);
3542
3543 return 0;
3544}
3545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546static int stop_output_stream(struct stream_out *out)
3547{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303548 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 struct audio_usecase *uc_info;
3550 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003551 bool has_voip_usecase =
3552 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553
Eric Laurent994a6932013-07-17 11:51:42 -07003554 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003555 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 uc_info = get_usecase_from_list(adev, out->usecase);
3557 if (uc_info == NULL) {
3558 ALOGE("%s: Could not find the usecase (%d) in the list",
3559 __func__, out->usecase);
3560 return -EINVAL;
3561 }
3562
Derek Chenea197282019-01-07 17:35:01 -08003563 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3564 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003565
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003566 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303567 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003568 if (adev->visualizer_stop_output != NULL)
3569 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003570
3571 audio_extn_dts_remove_state_notifier_node(out->usecase);
3572
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003573 if (adev->offload_effects_stop_output != NULL)
3574 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003575 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3576 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3577 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003578 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003579
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003580 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3581 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003582 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003583 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003584
Eric Laurent150dbfe2013-02-27 14:31:02 -08003585 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003586 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003587
3588 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003589 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590
Aalique Grahame22e49102018-12-18 14:23:57 -08003591 audio_extn_extspk_update(adev->extspk);
3592
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003593 if (is_offload_usecase(out->usecase)) {
3594 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3595 adev->dsp_bit_width_enforce_mode,
3596 false);
3597 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003598 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003599 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3600 false);
3601
3602 if (ret != 0)
3603 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3604 /* default service interval was successfully updated,
3605 reopen USB backend with new service interval */
3606 ret = 0;
3607 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003608
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003609 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303610 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003611 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303612 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003613 ALOGV("Disable passthrough , reset mixer to pcm");
3614 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003615#ifdef AUDIO_GKI_ENABLED
3616 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3617 out->compr_config.codec->reserved[0] = 0;
3618#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003619 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003620#endif
Mingming Yin21854652016-04-13 11:54:02 -07003621 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003622 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3623 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003624
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303625 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003626 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303627 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303628
Manish Dewangan21a850a2017-08-14 12:03:55 +05303629 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003630 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3631 if (ret < 0)
3632 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3633 }
3634
juyuchen2d415992018-11-16 14:15:16 +08003635 /* 1) media + voip output routing to handset must route media back to
3636 speaker when voip stops.
3637 2) trigger voip input to reroute when voip output changes to
3638 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003639 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003640 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003641 struct listnode *node;
3642 struct audio_usecase *usecase;
3643 list_for_each(node, &adev->usecase_list) {
3644 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003645 if ((usecase->type == PCM_CAPTURE &&
3646 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3647 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003648 continue;
3649
3650 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3651 __func__, usecase->id, use_case_table[usecase->id],
3652 out->usecase, use_case_table[out->usecase]);
3653 select_devices(adev, usecase->id);
3654 }
3655 }
3656
Garmond Leung5fd0b552018-04-17 11:56:12 -07003657 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003658 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 return ret;
3660}
3661
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003662struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3663 unsigned int flags, unsigned int pcm_open_retry_count,
3664 struct pcm_config *config)
3665{
3666 struct pcm* pcm = NULL;
3667
3668 while (1) {
3669 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3670 if (pcm == NULL || !pcm_is_ready(pcm)) {
3671 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3672 if (pcm != NULL) {
3673 pcm_close(pcm);
3674 pcm = NULL;
3675 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003676 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003677 return NULL;
3678
Weiyin Jiang72197252019-10-09 11:49:32 +08003679 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003680 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3681 continue;
3682 }
3683 break;
3684 }
3685
3686 if (pcm_is_ready(pcm)) {
3687 int ret = pcm_prepare(pcm);
3688 if (ret < 0) {
3689 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3690 pcm_close(pcm);
3691 pcm = NULL;
3692 }
3693 }
3694
3695 return pcm;
3696}
3697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698int start_output_stream(struct stream_out *out)
3699{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701 struct audio_usecase *uc_info;
3702 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003703 char mixer_ctl_name[128];
3704 struct mixer_ctl *ctl = NULL;
3705 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303706 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003707 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708
Haynes Mathew George380745d2017-10-04 15:27:45 -07003709 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003710 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3711 ret = -EINVAL;
3712 goto error_config;
3713 }
3714
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003715 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303716 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003717 get_device_types(&out->device_list), is_haptic_usecase);
3718
3719 bool is_speaker_active = compare_device_type(&out->device_list,
3720 AUDIO_DEVICE_OUT_SPEAKER);
3721 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3722 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303723
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303724 if (CARD_STATUS_OFFLINE == out->card_status ||
3725 CARD_STATUS_OFFLINE == adev->card_status) {
3726 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303727 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003728 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303729 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303730
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003731 //Update incall music usecase to reflect correct voice session
3732 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3733 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3734 if (ret != 0) {
3735 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3736 __func__, ret);
3737 goto error_config;
3738 }
3739 }
3740
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003741 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003742 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003743 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303744 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303745 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303746 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3747 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3748 ret = -EAGAIN;
3749 goto error_config;
3750 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303751 }
3752 }
3753 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003754 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303755 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003756 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303757 //combo usecase just by pass a2dp
3758 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003759 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303760 } else {
3761 ALOGE("%s: SCO profile is not ready, return error", __func__);
3762 ret = -EAGAIN;
3763 goto error_config;
3764 }
3765 }
3766 }
3767
Eric Laurentb23d5282013-05-14 15:27:20 -07003768 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769 if (out->pcm_device_id < 0) {
3770 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3771 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003772 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003773 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 }
3775
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003776 if (is_haptic_usecase) {
3777 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3778 if (adev->haptic_pcm_device_id < 0) {
3779 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3780 __func__, adev->haptic_pcm_device_id, out->usecase);
3781 ret = -EINVAL;
3782 goto error_config;
3783 }
3784 }
3785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003786 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003787
3788 if (!uc_info) {
3789 ret = -ENOMEM;
3790 goto error_config;
3791 }
3792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 uc_info->id = out->usecase;
3794 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003795 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003796 list_init(&uc_info->device_list);
3797 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003798 uc_info->in_snd_device = SND_DEVICE_NONE;
3799 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003800
3801 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003802 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003803 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3804 /* USB backend is not reopened immediately.
3805 This is eventually done as part of select_devices */
3806 }
3807
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003808 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809
Wei Wangf7ca6c92017-11-21 14:51:20 -08003810 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303811 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3812 adev->perf_lock_opts,
3813 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303814
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003815 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303816 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303817 if (audio_extn_passthru_is_enabled() &&
3818 audio_extn_passthru_is_passthrough_stream(out)) {
3819 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303820 }
3821 }
3822
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003823 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003824 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303825 if (!a2dp_combo) {
3826 check_a2dp_restore_l(adev, out, false);
3827 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003828 struct listnode dev;
3829 list_init(&dev);
3830 assign_devices(&dev, &out->device_list);
3831 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3832 reassign_device_list(&out->device_list,
3833 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003834 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003835 reassign_device_list(&out->device_list,
3836 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303837 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003838 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303839 }
3840 } else {
3841 select_devices(adev, out->usecase);
3842 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003843
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003844 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3845 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003846 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003847 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003848
Derek Chenea197282019-01-07 17:35:01 -08003849 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3850 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003851
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003852 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3853 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003854
3855 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003856 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003857 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3858 ALOGE("%s: pcm stream not ready", __func__);
3859 goto error_open;
3860 }
3861 ret = pcm_start(out->pcm);
3862 if (ret < 0) {
3863 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3864 goto error_open;
3865 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003866 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003867 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003868 unsigned int flags = PCM_OUT;
3869 unsigned int pcm_open_retry_count = 0;
3870 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3871 flags |= PCM_MMAP | PCM_NOIRQ;
3872 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003873 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003874 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003875 } else
3876 flags |= PCM_MONOTONIC;
3877
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003878 if ((adev->vr_audio_mode_enabled) &&
3879 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3880 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3881 "PCM_Dev %d Topology", out->pcm_device_id);
3882 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3883 if (!ctl) {
3884 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3885 __func__, mixer_ctl_name);
3886 } else {
3887 //if success use ULLPP
3888 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3889 __func__, mixer_ctl_name, out->pcm_device_id);
3890 //There is a still a possibility that some sessions
3891 // that request for FAST|RAW when 3D audio is active
3892 //can go through ULLPP. Ideally we expects apps to
3893 //listen to audio focus and stop concurrent playback
3894 //Also, we will look for mode flag (voice_in_communication)
3895 //before enabling the realtime flag.
3896 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3897 }
3898 }
3899
Surendar Karka91fa3682018-07-02 18:12:12 +05303900 if (out->realtime)
3901 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3902 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3903
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003904 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3905 flags, pcm_open_retry_count,
3906 &(out->config));
3907 if (out->pcm == NULL) {
3908 ret = -EIO;
3909 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003910 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003911
3912 if (is_haptic_usecase) {
3913 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3914 adev->haptic_pcm_device_id,
3915 flags, pcm_open_retry_count,
3916 &(adev->haptics_config));
3917 // failure to open haptics pcm shouldnt stop audio,
3918 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003919
3920 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3921 ALOGD("%s: enable haptic audio synchronization", __func__);
3922 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3923 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003924 }
3925
Surendar Karka91fa3682018-07-02 18:12:12 +05303926 if (!out->realtime)
3927 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303928 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003929
Zhou Song2b8f28f2017-09-11 10:51:38 +08003930 // apply volume for voip playback after path is set up
3931 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3932 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303933 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3934 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303935 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3936 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003937 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3938 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303939 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003940 } else {
Zhou Song79929fe2020-01-20 17:57:43 +08003941 /*
3942 * set custom channel map if:
3943 * 1. neither mono nor stereo clips i.e. channels > 2 OR
3944 * 2. custom channel map has been set by client
3945 * else default channel map of FC/FR/FL can always be set to DSP
3946 */
3947 if (popcount(out->channel_mask) > 2 || out->channel_map_param.channel_map[0])
3948 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3949 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003950 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3951 adev->dsp_bit_width_enforce_mode,
3952 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003954 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003955 out->compr = compress_open(adev->snd_card,
3956 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003957 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003958 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303959 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303960 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3961 adev->card_status = CARD_STATUS_OFFLINE;
3962 out->card_status = CARD_STATUS_OFFLINE;
3963 ret = -EIO;
3964 goto error_open;
3965 }
3966
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003967 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003968 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003969 compress_close(out->compr);
3970 out->compr = NULL;
3971 ret = -EIO;
3972 goto error_open;
3973 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303974 /* compress_open sends params of the track, so reset the flag here */
3975 out->is_compr_metadata_avail = false;
3976
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003977 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003978 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003979
Fred Oh3f43e742015-03-04 18:42:34 -08003980 /* Since small bufs uses blocking writes, a write will be blocked
3981 for the default max poll time (20s) in the event of an SSR.
3982 Reduce the poll time to observe and deal with SSR faster.
3983 */
Ashish Jain5106d362016-05-11 19:23:33 +05303984 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003985 compress_set_max_poll_wait(out->compr, 1000);
3986 }
3987
Manish Dewangan69426c82017-01-30 17:35:36 +05303988 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303989 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303990
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003991 audio_extn_dts_create_state_notifier_node(out->usecase);
3992 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3993 popcount(out->channel_mask),
3994 out->playback_started);
3995
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003996#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303997 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003998 audio_extn_dolby_send_ddp_endp_params(adev);
3999#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05304000 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
4001 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004002 if (adev->visualizer_start_output != NULL)
4003 adev->visualizer_start_output(out->handle, out->pcm_device_id);
4004 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05304005 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004006 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004007 }
Derek Chenf13dd492018-11-13 14:53:51 -08004008
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004009 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08004010 /* Update cached volume from media to offload/direct stream */
4011 struct listnode *node = NULL;
4012 list_for_each(node, &adev->active_outputs_list) {
4013 streams_output_ctxt_t *out_ctxt = node_to_item(node,
4014 streams_output_ctxt_t,
4015 list);
4016 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4017 out->volume_l = out_ctxt->output->volume_l;
4018 out->volume_r = out_ctxt->output->volume_r;
4019 }
4020 }
4021 out_set_compr_volume(&out->stream,
4022 out->volume_l, out->volume_r);
4023 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004025
4026 if (ret == 0) {
4027 register_out_stream(out);
4028 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004029 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4030 ALOGE("%s: pcm stream not ready", __func__);
4031 goto error_open;
4032 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004033 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004034 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004035 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004036 if (ret < 0)
4037 goto error_open;
4038 }
4039 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004040 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304041 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004042 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004043
vivek mehtad15d2bf2019-05-17 13:35:10 -07004044 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4045 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4046 audio_low_latency_hint_start();
4047 }
4048
Manish Dewangan21a850a2017-08-14 12:03:55 +05304049 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004050 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004051 if (ret < 0)
4052 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4053 }
4054
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004055 // consider a scenario where on pause lower layers are tear down.
4056 // so on resume, swap mixer control need to be sent only when
4057 // backend is active, hence rather than sending from enable device
4058 // sending it from start of streamtream
4059
4060 platform_set_swap_channels(adev, true);
4061
Haynes Mathew George380745d2017-10-04 15:27:45 -07004062 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304063 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004064 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004065error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004066 if (adev->haptic_pcm) {
4067 pcm_close(adev->haptic_pcm);
4068 adev->haptic_pcm = NULL;
4069 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004070 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304071 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004072 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004073error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304074 /*
4075 * sleep 50ms to allow sufficient time for kernel
4076 * drivers to recover incases like SSR.
4077 */
4078 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004079error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004080 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304081 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004082 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004083}
4084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085static int check_input_parameters(uint32_t sample_rate,
4086 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004087 int channel_count,
4088 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004090 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304092 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4093 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4094 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004095 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004096 !audio_extn_compr_cap_format_supported(format) &&
4097 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004098 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004099
Aalique Grahame22e49102018-12-18 14:23:57 -08004100 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4101 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4102 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4103 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4104 return -EINVAL;
4105 }
4106
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004107 switch (channel_count) {
4108 case 1:
4109 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304110 case 3:
4111 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004112 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004113 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304114 case 10:
4115 case 12:
4116 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004117 break;
4118 default:
4119 ret = -EINVAL;
4120 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121
4122 switch (sample_rate) {
4123 case 8000:
4124 case 11025:
4125 case 12000:
4126 case 16000:
4127 case 22050:
4128 case 24000:
4129 case 32000:
4130 case 44100:
4131 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004132 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304133 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004134 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304135 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004136 break;
4137 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004138 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139 }
4140
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004141 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142}
4143
Naresh Tanniru04f71882018-06-26 17:46:22 +05304144
4145/** Add a value in a list if not already present.
4146 * @return true if value was successfully inserted or already present,
4147 * false if the list is full and does not contain the value.
4148 */
4149static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4150 for (size_t i = 0; i < list_length; i++) {
4151 if (list[i] == value) return true; // value is already present
4152 if (list[i] == 0) { // no values in this slot
4153 list[i] = value;
4154 return true; // value inserted
4155 }
4156 }
4157 return false; // could not insert value
4158}
4159
4160/** Add channel_mask in supported_channel_masks if not already present.
4161 * @return true if channel_mask was successfully inserted or already present,
4162 * false if supported_channel_masks is full and does not contain channel_mask.
4163 */
4164static void register_channel_mask(audio_channel_mask_t channel_mask,
4165 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4166 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4167 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4168}
4169
4170/** Add format in supported_formats if not already present.
4171 * @return true if format was successfully inserted or already present,
4172 * false if supported_formats is full and does not contain format.
4173 */
4174static void register_format(audio_format_t format,
4175 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4176 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4177 "%s: stream can not declare supporting its format %x", __func__, format);
4178}
4179/** Add sample_rate in supported_sample_rates if not already present.
4180 * @return true if sample_rate was successfully inserted or already present,
4181 * false if supported_sample_rates is full and does not contain sample_rate.
4182 */
4183static void register_sample_rate(uint32_t sample_rate,
4184 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4185 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4186 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4187}
4188
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004189static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4190{
4191 uint32_t high = num1, low = num2, temp = 0;
4192
4193 if (!num1 || !num2)
4194 return 0;
4195
4196 if (num1 < num2) {
4197 high = num2;
4198 low = num1;
4199 }
4200
4201 while (low != 0) {
4202 temp = low;
4203 low = high % low;
4204 high = temp;
4205 }
4206 return (num1 * num2)/high;
4207}
4208
4209static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4210{
4211 uint32_t remainder = 0;
4212
4213 if (!multiplier)
4214 return num;
4215
4216 remainder = num % multiplier;
4217 if (remainder)
4218 num += (multiplier - remainder);
4219
4220 return num;
4221}
4222
Aalique Grahame22e49102018-12-18 14:23:57 -08004223static size_t get_stream_buffer_size(size_t duration_ms,
4224 uint32_t sample_rate,
4225 audio_format_t format,
4226 int channel_count,
4227 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004228{
4229 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004230 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231
Aalique Grahame22e49102018-12-18 14:23:57 -08004232 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004233 if (is_low_latency)
4234 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304235
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004236 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004237 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238
Ralf Herzbd08d632018-09-28 15:50:49 +02004239 /* make sure the size is multiple of 32 bytes and additionally multiple of
4240 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004241 * At 48 kHz mono 16-bit PCM:
4242 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4243 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004244 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004245 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004246 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004247
4248 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004249}
4250
Aalique Grahame22e49102018-12-18 14:23:57 -08004251static size_t get_input_buffer_size(uint32_t sample_rate,
4252 audio_format_t format,
4253 int channel_count,
4254 bool is_low_latency)
4255{
4256 /* Don't know if USB HIFI in this context so use true to be conservative */
4257 if (check_input_parameters(sample_rate, format, channel_count,
4258 true /*is_usb_hifi */) != 0)
4259 return 0;
4260
4261 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4262 sample_rate,
4263 format,
4264 channel_count,
4265 is_low_latency);
4266}
4267
Derek Chenf6318be2017-06-12 17:16:24 -04004268size_t get_output_period_size(uint32_t sample_rate,
4269 audio_format_t format,
4270 int channel_count,
4271 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304272{
4273 size_t size = 0;
4274 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4275
4276 if ((duration == 0) || (sample_rate == 0) ||
4277 (bytes_per_sample == 0) || (channel_count == 0)) {
4278 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4279 bytes_per_sample, channel_count);
4280 return -EINVAL;
4281 }
4282
4283 size = (sample_rate *
4284 duration *
4285 bytes_per_sample *
4286 channel_count) / 1000;
4287 /*
4288 * To have same PCM samples for all channels, the buffer size requires to
4289 * be multiple of (number of channels * bytes per sample)
4290 * For writes to succeed, the buffer must be written at address which is multiple of 32
4291 */
4292 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4293
4294 return (size/(channel_count * bytes_per_sample));
4295}
4296
Zhou Song48453a02018-01-10 17:50:59 +08004297static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304298{
4299 uint64_t actual_frames_rendered = 0;
4300 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4301
4302 /* This adjustment accounts for buffering after app processor.
4303 * It is based on estimated DSP latency per use case, rather than exact.
4304 */
Robert Lee58215542019-07-15 20:55:12 +08004305 pthread_mutex_lock(&adev->lock);
4306 int64_t platform_latency = platform_render_latency(out->dev, out->usecase) *
Ashish Jain5106d362016-05-11 19:23:33 +05304307 out->sample_rate / 1000000LL;
Robert Lee58215542019-07-15 20:55:12 +08004308 pthread_mutex_unlock(&adev->lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304309
Zhou Song48453a02018-01-10 17:50:59 +08004310 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304311 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4312 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4313 * hence only estimate.
4314 */
George Gao62ebc722019-07-29 16:29:44 -07004315 uint64_t signed_frames = 0;
4316 if (out->written >= kernel_buffer_size)
4317 signed_frames = out->written - kernel_buffer_size;
Ashish Jain5106d362016-05-11 19:23:33 +05304318
George Gao62ebc722019-07-29 16:29:44 -07004319 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask));
4320 if (signed_frames >= platform_latency)
4321 signed_frames = signed_frames - platform_latency;
Ashish Jain5106d362016-05-11 19:23:33 +05304322
Zhou Song48453a02018-01-10 17:50:59 +08004323 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304324 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004325 if (timestamp != NULL )
4326 *timestamp = out->writeAt;
4327 } else if (timestamp != NULL) {
4328 clock_gettime(CLOCK_MONOTONIC, timestamp);
4329 }
4330 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304331
4332 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
George Gao62ebc722019-07-29 16:29:44 -07004333 "bytes/sample %zu channel count %d", __func__, signed_frames,
Ashish Jain5106d362016-05-11 19:23:33 +05304334 (long long int)out->written, (int)kernel_buffer_size,
4335 audio_bytes_per_sample(out->compr_config.codec->format),
4336 popcount(out->channel_mask));
4337
4338 return actual_frames_rendered;
4339}
4340
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4342{
4343 struct stream_out *out = (struct stream_out *)stream;
4344
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004345 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004346}
4347
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004348static int out_set_sample_rate(struct audio_stream *stream __unused,
4349 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004350{
4351 return -ENOSYS;
4352}
4353
4354static size_t out_get_buffer_size(const struct audio_stream *stream)
4355{
4356 struct stream_out *out = (struct stream_out *)stream;
4357
Varun Balaraje49253e2017-07-06 19:48:56 +05304358 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304359 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304360 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304361 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4362 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4363 else
4364 return out->compr_config.fragment_size;
4365 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004366 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304367 else if (is_offload_usecase(out->usecase) &&
4368 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304369 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004370
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004371 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004372 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373}
4374
4375static uint32_t out_get_channels(const struct audio_stream *stream)
4376{
4377 struct stream_out *out = (struct stream_out *)stream;
4378
4379 return out->channel_mask;
4380}
4381
4382static audio_format_t out_get_format(const struct audio_stream *stream)
4383{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004384 struct stream_out *out = (struct stream_out *)stream;
4385
4386 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387}
4388
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004389static int out_set_format(struct audio_stream *stream __unused,
4390 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004391{
4392 return -ENOSYS;
4393}
4394
4395static int out_standby(struct audio_stream *stream)
4396{
4397 struct stream_out *out = (struct stream_out *)stream;
4398 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004399 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004400
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304401 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4402 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004404 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004405 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004406 if (adev->adm_deregister_stream)
4407 adev->adm_deregister_stream(adev->adm_data, out->handle);
4408
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004409 if (is_offload_usecase(out->usecase))
4410 stop_compressed_output_l(out);
4411
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004412 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004413 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004414 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4415 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304416 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004417 pthread_mutex_unlock(&adev->lock);
4418 pthread_mutex_unlock(&out->lock);
4419 ALOGD("VOIP output entered standby");
4420 return 0;
4421 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004422 if (out->pcm) {
4423 pcm_close(out->pcm);
4424 out->pcm = NULL;
4425 }
Meng Wanga09da002020-04-20 12:56:04 +08004426 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4427 if (adev->haptic_pcm) {
4428 pcm_close(adev->haptic_pcm);
4429 adev->haptic_pcm = NULL;
4430 }
4431
4432 if (adev->haptic_buffer != NULL) {
4433 free(adev->haptic_buffer);
4434 adev->haptic_buffer = NULL;
4435 adev->haptic_buffer_size = 0;
4436 }
4437 adev->haptic_pcm_device_id = 0;
4438 }
4439
Haynes Mathew George16081042017-05-31 17:16:49 -07004440 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4441 do_stop = out->playback_started;
4442 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004443
4444 if (out->mmap_shared_memory_fd >= 0) {
4445 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4446 __func__, out->mmap_shared_memory_fd);
4447 close(out->mmap_shared_memory_fd);
4448 out->mmap_shared_memory_fd = -1;
4449 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004450 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004451 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004452 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304453 out->send_next_track_params = false;
4454 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004455 out->gapless_mdata.encoder_delay = 0;
4456 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004457 if (out->compr != NULL) {
4458 compress_close(out->compr);
4459 out->compr = NULL;
4460 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004461 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004462 if (do_stop) {
4463 stop_output_stream(out);
4464 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304465 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004466 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004467 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004468 }
4469 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304470 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004471 return 0;
4472}
4473
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304474static int out_on_error(struct audio_stream *stream)
4475{
4476 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004477 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304478
4479 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004480 // always send CMD_ERROR for offload streams, this
4481 // is needed e.g. when SSR happens within compress_open
4482 // since the stream is active, offload_callback_thread is also active.
4483 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4484 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004485 }
4486 pthread_mutex_unlock(&out->lock);
4487
4488 status = out_standby(&out->stream.common);
4489
4490 lock_output_stream(out);
4491 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004492 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304493 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304494
4495 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4496 ALOGD("Setting previous card status if offline");
4497 out->prev_card_status_offline = true;
4498 }
4499
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304500 pthread_mutex_unlock(&out->lock);
4501
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004502 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304503}
4504
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304505/*
4506 *standby implementation without locks, assumes that the callee already
4507 *has taken adev and out lock.
4508 */
4509int out_standby_l(struct audio_stream *stream)
4510{
4511 struct stream_out *out = (struct stream_out *)stream;
4512 struct audio_device *adev = out->dev;
4513
4514 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4515 stream, out->usecase, use_case_table[out->usecase]);
4516
4517 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004518 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304519 if (adev->adm_deregister_stream)
4520 adev->adm_deregister_stream(adev->adm_data, out->handle);
4521
4522 if (is_offload_usecase(out->usecase))
4523 stop_compressed_output_l(out);
4524
4525 out->standby = true;
4526 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4527 voice_extn_compress_voip_close_output_stream(stream);
4528 out->started = 0;
4529 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004530 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304531 return 0;
4532 } else if (!is_offload_usecase(out->usecase)) {
4533 if (out->pcm) {
4534 pcm_close(out->pcm);
4535 out->pcm = NULL;
4536 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004537 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4538 if (adev->haptic_pcm) {
4539 pcm_close(adev->haptic_pcm);
4540 adev->haptic_pcm = NULL;
4541 }
4542
4543 if (adev->haptic_buffer != NULL) {
4544 free(adev->haptic_buffer);
4545 adev->haptic_buffer = NULL;
4546 adev->haptic_buffer_size = 0;
4547 }
4548 adev->haptic_pcm_device_id = 0;
4549 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304550 } else {
4551 ALOGD("copl(%p):standby", out);
4552 out->send_next_track_params = false;
4553 out->is_compr_metadata_avail = false;
4554 out->gapless_mdata.encoder_delay = 0;
4555 out->gapless_mdata.encoder_padding = 0;
4556 if (out->compr != NULL) {
4557 compress_close(out->compr);
4558 out->compr = NULL;
4559 }
4560 }
4561 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004562 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304563 }
4564 ALOGD("%s: exit", __func__);
4565 return 0;
4566}
4567
Aalique Grahame22e49102018-12-18 14:23:57 -08004568static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004569{
Aalique Grahame22e49102018-12-18 14:23:57 -08004570 struct stream_out *out = (struct stream_out *)stream;
4571
4572 // We try to get the lock for consistency,
4573 // but it isn't necessary for these variables.
4574 // If we're not in standby, we may be blocked on a write.
4575 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4576 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4577 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4578
Andy Hunga1f48fa2019-07-01 18:14:53 -07004579 char buffer[256]; // for statistics formatting
4580 if (!is_offload_usecase(out->usecase)) {
4581 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
4582 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
4583 }
4584
Andy Hungc6bfd4a2019-07-01 18:26:00 -07004585 if (out->start_latency_ms.n > 0) {
4586 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
4587 dprintf(fd, " Start latency ms: %s\n", buffer);
4588 }
4589
Aalique Grahame22e49102018-12-18 14:23:57 -08004590 if (locked) {
4591 pthread_mutex_unlock(&out->lock);
4592 }
4593
4594 // dump error info
4595 (void)error_log_dump(
4596 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598 return 0;
4599}
4600
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004601static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4602{
4603 int ret = 0;
4604 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004605
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004606 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004607 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004608 return -EINVAL;
4609 }
4610
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304611 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004612
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004613 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4614 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304615 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004616 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004617 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4618 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304619 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004620 }
4621
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004622 ALOGV("%s new encoder delay %u and padding %u", __func__,
4623 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4624
4625 return 0;
4626}
4627
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004628static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4629{
4630 return out == adev->primary_output || out == adev->voice_tx_output;
4631}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004632
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304633// note: this call is safe only if the stream_cb is
4634// removed first in close_output_stream (as is done now).
4635static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4636{
4637 if (!stream || !parms)
4638 return;
4639
4640 struct stream_out *out = (struct stream_out *)stream;
4641 struct audio_device *adev = out->dev;
4642
4643 card_status_t status;
4644 int card;
4645 if (parse_snd_card_status(parms, &card, &status) < 0)
4646 return;
4647
4648 pthread_mutex_lock(&adev->lock);
4649 bool valid_cb = (card == adev->snd_card);
4650 pthread_mutex_unlock(&adev->lock);
4651
4652 if (!valid_cb)
4653 return;
4654
4655 lock_output_stream(out);
4656 if (out->card_status != status)
4657 out->card_status = status;
4658 pthread_mutex_unlock(&out->lock);
4659
4660 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4661 use_case_table[out->usecase],
4662 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4663
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304664 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304665 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304666 if (voice_is_call_state_active(adev) &&
4667 out == adev->primary_output) {
4668 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4669 pthread_mutex_lock(&adev->lock);
4670 voice_stop_call(adev);
4671 adev->mode = AUDIO_MODE_NORMAL;
4672 pthread_mutex_unlock(&adev->lock);
4673 }
4674 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304675 return;
4676}
4677
Kevin Rocardfce19002017-08-07 19:21:36 -07004678static int get_alive_usb_card(struct str_parms* parms) {
4679 int card;
4680 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4681 !audio_extn_usb_alive(card)) {
4682 return card;
4683 }
4684 return -ENODEV;
4685}
4686
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004687int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004688 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004689{
4690 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004691 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004692 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004693 bool bypass_a2dp = false;
4694 bool reconfig = false;
4695 unsigned long service_interval = 0;
4696
4697 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004698 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4699
4700 list_init(&new_devices);
4701 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004702
4703 lock_output_stream(out);
4704 pthread_mutex_lock(&adev->lock);
4705
4706 /*
4707 * When HDMI cable is unplugged the music playback is paused and
4708 * the policy manager sends routing=0. But the audioflinger continues
4709 * to write data until standby time (3sec). As the HDMI core is
4710 * turned off, the write gets blocked.
4711 * Avoid this by routing audio to speaker until standby.
4712 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004713 if (is_single_device_type_equal(&out->device_list,
4714 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004715 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004716 !audio_extn_passthru_is_passthrough_stream(out) &&
4717 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004718 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004719 }
4720 /*
4721 * When A2DP is disconnected the
4722 * music playback is paused and the policy manager sends routing=0
4723 * But the audioflinger continues to write data until standby time
4724 * (3sec). As BT is turned off, the write gets blocked.
4725 * Avoid this by routing audio to speaker until standby.
4726 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004727 if (is_a2dp_out_device_type(&out->device_list) &&
4728 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004729 !audio_extn_a2dp_source_is_ready() &&
4730 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004731 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004732 }
4733 /*
4734 * When USB headset is disconnected the music platback paused
4735 * and the policy manager send routing=0. But if the USB is connected
4736 * back before the standby time, AFE is not closed and opened
4737 * when USB is connected back. So routing to speker will guarantee
4738 * AFE reconfiguration and AFE will be opend once USB is connected again
4739 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004740 if (is_usb_out_device_type(&out->device_list) &&
4741 list_empty(&new_devices) &&
4742 !audio_extn_usb_connected(NULL)) {
4743 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4744 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004745 /* To avoid a2dp to sco overlapping / BT device improper state
4746 * check with BT lib about a2dp streaming support before routing
4747 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004748 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004749 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004750 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4751 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004752 //combo usecase just by pass a2dp
4753 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4754 bypass_a2dp = true;
4755 } else {
4756 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4757 /* update device to a2dp and don't route as BT returned error
4758 * However it is still possible a2dp routing called because
4759 * of current active device disconnection (like wired headset)
4760 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004761 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004762 pthread_mutex_unlock(&adev->lock);
4763 pthread_mutex_unlock(&out->lock);
4764 goto error;
4765 }
4766 }
4767 }
4768
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004769 // Workaround: If routing to an non existing usb device, fail gracefully
4770 // The routing request will otherwise block during 10 second
4771 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004772 if (is_usb_out_device_type(&new_devices)) {
4773 struct str_parms *parms =
4774 str_parms_create_str(get_usb_device_address(&new_devices));
4775 if (!parms)
4776 goto error;
4777 if ((card = get_alive_usb_card(parms)) >= 0) {
4778 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4779 pthread_mutex_unlock(&adev->lock);
4780 pthread_mutex_unlock(&out->lock);
4781 str_parms_destroy(parms);
4782 ret = -ENOSYS;
4783 goto error;
4784 }
4785 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004786 }
4787
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004788 // Workaround: If routing to an non existing hdmi device, fail gracefully
4789 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4790 (platform_get_edid_info_v2(adev->platform,
4791 out->extconn.cs.controller,
4792 out->extconn.cs.stream) != 0)) {
4793 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4794 pthread_mutex_unlock(&adev->lock);
4795 pthread_mutex_unlock(&out->lock);
4796 ret = -ENOSYS;
4797 goto error;
4798 }
4799
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004800 /*
4801 * select_devices() call below switches all the usecases on the same
4802 * backend to the new device. Refer to check_usecases_codec_backend() in
4803 * the select_devices(). But how do we undo this?
4804 *
4805 * For example, music playback is active on headset (deep-buffer usecase)
4806 * and if we go to ringtones and select a ringtone, low-latency usecase
4807 * will be started on headset+speaker. As we can't enable headset+speaker
4808 * and headset devices at the same time, select_devices() switches the music
4809 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4810 * So when the ringtone playback is completed, how do we undo the same?
4811 *
4812 * We are relying on the out_set_parameters() call on deep-buffer output,
4813 * once the ringtone playback is ended.
4814 * NOTE: We should not check if the current devices are same as new devices.
4815 * Because select_devices() must be called to switch back the music
4816 * playback to headset.
4817 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004818 if (!list_empty(&new_devices)) {
4819 bool same_dev = compare_devices(&out->device_list, &new_devices);
4820 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004821
4822 if (output_drives_call(adev, out)) {
4823 if (!voice_is_call_state_active(adev)) {
4824 if (adev->mode == AUDIO_MODE_IN_CALL) {
4825 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004826 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004827 service_interval =
4828 audio_extn_usb_find_service_interval(true, true /*playback*/);
4829 audio_extn_usb_set_service_interval(true /*playback*/,
4830 service_interval,
4831 &reconfig);
4832 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4833 }
4834 ret = voice_start_call(adev);
4835 }
4836 } else {
4837 adev->current_call_output = out;
4838 voice_update_devices_for_all_voice_usecases(adev);
4839 }
4840 }
4841
4842 if (!out->standby) {
4843 if (!same_dev) {
4844 ALOGV("update routing change");
4845 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4846 adev->perf_lock_opts,
4847 adev->perf_lock_opts_size);
4848 if (adev->adm_on_routing_change)
4849 adev->adm_on_routing_change(adev->adm_data,
4850 out->handle);
4851 }
4852 if (!bypass_a2dp) {
4853 select_devices(adev, out->usecase);
4854 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004855 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4856 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004857 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004858 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004859 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004860 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004861 }
4862
4863 if (!same_dev) {
4864 // on device switch force swap, lower functions will make sure
4865 // to check if swap is allowed or not.
4866 platform_set_swap_channels(adev, true);
4867 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4868 }
4869 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4870 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004871 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004872 pthread_mutex_lock(&out->compr_mute_lock);
4873 out->a2dp_compress_mute = false;
4874 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4875 pthread_mutex_unlock(&out->compr_mute_lock);
4876 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4877 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4878 }
4879 }
4880 }
4881
4882 pthread_mutex_unlock(&adev->lock);
4883 pthread_mutex_unlock(&out->lock);
4884
4885 /*handles device and call state changes*/
4886 audio_extn_extspk_update(adev->extspk);
4887
4888error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004889 ALOGV("%s: exit: code(%d)", __func__, ret);
4890 return ret;
4891}
4892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004893static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4894{
4895 struct stream_out *out = (struct stream_out *)stream;
4896 struct audio_device *adev = out->dev;
4897 struct str_parms *parms;
4898 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004899 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004900 int ext_controller = -1;
4901 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004902
sangwoobc677242013-08-08 16:53:43 +09004903 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004904 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004905 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304906 if (!parms)
4907 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004908
4909 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4910 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08004911 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004912 out->extconn.cs.controller = ext_controller;
4913 out->extconn.cs.stream = ext_stream;
4914 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4915 use_case_table[out->usecase], out->extconn.cs.controller,
4916 out->extconn.cs.stream);
4917 }
4918
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004919 if (out == adev->primary_output) {
4920 pthread_mutex_lock(&adev->lock);
4921 audio_extn_set_parameters(adev, parms);
4922 pthread_mutex_unlock(&adev->lock);
4923 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004924 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004925 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004926 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004927
4928 audio_extn_dts_create_state_notifier_node(out->usecase);
4929 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4930 popcount(out->channel_mask),
4931 out->playback_started);
4932
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004933 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004934 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004935
Surendar Karkaf51b5842018-04-26 11:28:38 +05304936 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4937 sizeof(value));
4938 if (err >= 0) {
4939 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4940 audio_extn_send_dual_mono_mixing_coefficients(out);
4941 }
4942
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304943 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4944 if (err >= 0) {
4945 strlcpy(out->profile, value, sizeof(out->profile));
4946 ALOGV("updating stream profile with value '%s'", out->profile);
4947 lock_output_stream(out);
4948 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4949 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004950 &out->device_list, out->flags,
4951 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304952 out->sample_rate, out->bit_width,
4953 out->channel_mask, out->profile,
4954 &out->app_type_cfg);
4955 pthread_mutex_unlock(&out->lock);
4956 }
4957
Alexy Joseph98988832017-01-13 14:56:59 -08004958 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004959 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4960 // and vendor.audio.hal.output.suspend.supported is set to true
4961 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004962 //check suspend parameter only for low latency and if the property
4963 //is enabled
4964 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4965 ALOGI("%s: got suspend_playback %s", __func__, value);
4966 lock_output_stream(out);
4967 if (!strncmp(value, "false", 5)) {
4968 //suspend_playback=false is supposed to set QOS value back to 75%
4969 //the mixer control sent with value Enable will achieve that
4970 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4971 } else if (!strncmp (value, "true", 4)) {
4972 //suspend_playback=true is supposed to remove QOS value
4973 //resetting the mixer control will set the default value
4974 //for the mixer control which is Disable and this removes the QOS vote
4975 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4976 } else {
4977 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4978 " got %s", __func__, value);
4979 ret = -1;
4980 }
4981
4982 if (ret != 0) {
4983 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4984 __func__, out->pm_qos_mixer_path, ret);
4985 }
4986
4987 pthread_mutex_unlock(&out->lock);
4988 }
4989 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004990
Alexy Joseph98988832017-01-13 14:56:59 -08004991 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004992 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304993error:
Eric Laurent994a6932013-07-17 11:51:42 -07004994 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004995 return ret;
4996}
4997
Paul McLeana50b7332018-12-17 08:24:21 -07004998static int in_set_microphone_direction(const struct audio_stream_in *stream,
4999 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07005000 struct stream_in *in = (struct stream_in *)stream;
5001
5002 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
5003
5004 in->direction = dir;
5005
5006 if (in->standby)
5007 return 0;
5008
5009 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07005010}
5011
5012static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07005013 struct stream_in *in = (struct stream_in *)stream;
5014
5015 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
5016
5017 if (zoom > 1.0 || zoom < -1.0)
5018 return -EINVAL;
5019
5020 in->zoom = zoom;
5021
5022 if (in->standby)
5023 return 0;
5024
5025 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07005026}
5027
5028
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005029static bool stream_get_parameter_channels(struct str_parms *query,
5030 struct str_parms *reply,
5031 audio_channel_mask_t *supported_channel_masks) {
5032 int ret = -1;
5033 char value[512];
5034 bool first = true;
5035 size_t i, j;
5036
5037 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
5038 ret = 0;
5039 value[0] = '\0';
5040 i = 0;
5041 while (supported_channel_masks[i] != 0) {
5042 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5043 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5044 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305045 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005046
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305047 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005048 first = false;
5049 break;
5050 }
5051 }
5052 i++;
5053 }
5054 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5055 }
5056 return ret == 0;
5057}
5058
5059static bool stream_get_parameter_formats(struct str_parms *query,
5060 struct str_parms *reply,
5061 audio_format_t *supported_formats) {
5062 int ret = -1;
5063 char value[256];
5064 size_t i, j;
5065 bool first = true;
5066
5067 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5068 ret = 0;
5069 value[0] = '\0';
5070 i = 0;
5071 while (supported_formats[i] != 0) {
5072 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5073 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5074 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305075 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005076 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305077 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005078 first = false;
5079 break;
5080 }
5081 }
5082 i++;
5083 }
5084 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5085 }
5086 return ret == 0;
5087}
5088
5089static bool stream_get_parameter_rates(struct str_parms *query,
5090 struct str_parms *reply,
5091 uint32_t *supported_sample_rates) {
5092
5093 int i;
5094 char value[256];
5095 int ret = -1;
5096 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5097 ret = 0;
5098 value[0] = '\0';
5099 i=0;
5100 int cursor = 0;
5101 while (supported_sample_rates[i]) {
5102 int avail = sizeof(value) - cursor;
5103 ret = snprintf(value + cursor, avail, "%s%d",
5104 cursor > 0 ? "|" : "",
5105 supported_sample_rates[i]);
5106 if (ret < 0 || ret >= avail) {
5107 // if cursor is at the last element of the array
5108 // overwrite with \0 is duplicate work as
5109 // snprintf already put a \0 in place.
5110 // else
5111 // we had space to write the '|' at value[cursor]
5112 // (which will be overwritten) or no space to fill
5113 // the first element (=> cursor == 0)
5114 value[cursor] = '\0';
5115 break;
5116 }
5117 cursor += ret;
5118 ++i;
5119 }
5120 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5121 value);
5122 }
5123 return ret >= 0;
5124}
5125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005126static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5127{
5128 struct stream_out *out = (struct stream_out *)stream;
5129 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005130 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005131 char value[256];
5132 struct str_parms *reply = str_parms_create();
5133 size_t i, j;
5134 int ret;
5135 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005136
5137 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005138 if (reply) {
5139 str_parms_destroy(reply);
5140 }
5141 if (query) {
5142 str_parms_destroy(query);
5143 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005144 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5145 return NULL;
5146 }
5147
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005148 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005149 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5150 if (ret >= 0) {
5151 value[0] = '\0';
5152 i = 0;
5153 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005154 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5155 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005156 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005157 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005158 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005159 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005160 first = false;
5161 break;
5162 }
5163 }
5164 i++;
5165 }
5166 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5167 str = str_parms_to_str(reply);
5168 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005169 voice_extn_out_get_parameters(out, query, reply);
5170 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005171 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005172
Alexy Joseph62142aa2015-11-16 15:10:34 -08005173
5174 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5175 if (ret >= 0) {
5176 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305177 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5178 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005179 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305180 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005181 } else {
5182 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305183 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005184 }
5185 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005186 if (str)
5187 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005188 str = str_parms_to_str(reply);
5189 }
5190
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005191 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5192 if (ret >= 0) {
5193 value[0] = '\0';
5194 i = 0;
5195 first = true;
5196 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005197 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5198 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005199 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005200 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005201 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005202 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005203 first = false;
5204 break;
5205 }
5206 }
5207 i++;
5208 }
5209 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005210 if (str)
5211 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005212 str = str_parms_to_str(reply);
5213 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005214
5215 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5216 if (ret >= 0) {
5217 value[0] = '\0';
5218 i = 0;
5219 first = true;
5220 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005221 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5222 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005223 if (!first) {
5224 strlcat(value, "|", sizeof(value));
5225 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005226 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005227 first = false;
5228 break;
5229 }
5230 }
5231 i++;
5232 }
5233 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5234 if (str)
5235 free(str);
5236 str = str_parms_to_str(reply);
5237 }
5238
Alexy Joseph98988832017-01-13 14:56:59 -08005239 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5240 //only low latency track supports suspend_resume
5241 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005242 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005243 if (str)
5244 free(str);
5245 str = str_parms_to_str(reply);
5246 }
5247
5248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005249 str_parms_destroy(query);
5250 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005251 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005252 return str;
5253}
5254
5255static uint32_t out_get_latency(const struct audio_stream_out *stream)
5256{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005257 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005258 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005259 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005260
Alexy Josephaa54c872014-12-03 02:46:47 -08005261 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305262 lock_output_stream(out);
5263 latency = audio_extn_utils_compress_get_dsp_latency(out);
5264 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005265 } else if ((out->realtime) ||
5266 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005267 // since the buffer won't be filled up faster than realtime,
5268 // return a smaller number
5269 if (out->config.rate)
5270 period_ms = (out->af_period_multiplier * out->config.period_size *
5271 1000) / (out->config.rate);
5272 else
5273 period_ms = 0;
Robert Lee58215542019-07-15 20:55:12 +08005274 pthread_mutex_lock(&adev->lock);
5275 latency = period_ms + platform_render_latency(out->dev, out->usecase)/1000;
5276 pthread_mutex_unlock(&adev->lock);
Alexy Josephaa54c872014-12-03 02:46:47 -08005277 } else {
5278 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005279 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005280 }
5281
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005282 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005283 latency += audio_extn_a2dp_get_encoder_latency();
5284
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305285 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005286 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005287}
5288
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305289static float AmpToDb(float amplification)
5290{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305291 float db = DSD_VOLUME_MIN_DB;
5292 if (amplification > 0) {
5293 db = 20 * log10(amplification);
5294 if(db < DSD_VOLUME_MIN_DB)
5295 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305296 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305297 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305298}
5299
Arun Mirpuri5d170872019-03-26 13:21:31 -07005300static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5301 float right)
5302{
5303 struct stream_out *out = (struct stream_out *)stream;
5304 long volume = 0;
5305 char mixer_ctl_name[128] = "";
5306 struct audio_device *adev = out->dev;
5307 struct mixer_ctl *ctl = NULL;
5308 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5309 PCM_PLAYBACK);
5310
5311 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5312 "Playback %d Volume", pcm_device_id);
5313 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5314 if (!ctl) {
5315 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5316 __func__, mixer_ctl_name);
5317 return -EINVAL;
5318 }
5319 if (left != right)
5320 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5321 __func__, left, right);
5322 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5323 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5324 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5325 __func__, mixer_ctl_name, volume);
5326 return -EINVAL;
5327 }
5328 return 0;
5329}
5330
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305331static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5332 float right)
5333{
5334 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305335 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305336 char mixer_ctl_name[128];
5337 struct audio_device *adev = out->dev;
5338 struct mixer_ctl *ctl;
5339 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5340 PCM_PLAYBACK);
5341
5342 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5343 "Compress Playback %d Volume", pcm_device_id);
5344 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5345 if (!ctl) {
5346 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5347 __func__, mixer_ctl_name);
5348 return -EINVAL;
5349 }
5350 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5351 __func__, mixer_ctl_name, left, right);
5352 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5353 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5354 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5355
5356 return 0;
5357}
5358
Zhou Song2b8f28f2017-09-11 10:51:38 +08005359static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5360 float right)
5361{
5362 struct stream_out *out = (struct stream_out *)stream;
5363 char mixer_ctl_name[] = "App Type Gain";
5364 struct audio_device *adev = out->dev;
5365 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305366 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005367
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005368 if (!is_valid_volume(left, right)) {
5369 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5370 __func__, left, right);
5371 return -EINVAL;
5372 }
5373
Zhou Song2b8f28f2017-09-11 10:51:38 +08005374 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5375 if (!ctl) {
5376 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5377 __func__, mixer_ctl_name);
5378 return -EINVAL;
5379 }
5380
5381 set_values[0] = 0; //0: Rx Session 1:Tx Session
5382 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305383 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5384 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005385
5386 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5387 return 0;
5388}
5389
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305390static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5391 float right)
5392{
5393 struct stream_out *out = (struct stream_out *)stream;
5394 /* Volume control for pcm playback */
5395 if (left != right) {
5396 return -EINVAL;
5397 } else {
5398 char mixer_ctl_name[128];
5399 struct audio_device *adev = out->dev;
5400 struct mixer_ctl *ctl;
5401 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5402 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5403 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5404 if (!ctl) {
5405 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5406 return -EINVAL;
5407 }
5408
5409 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5410 int ret = mixer_ctl_set_value(ctl, 0, volume);
5411 if (ret < 0) {
5412 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5413 return -EINVAL;
5414 }
5415
5416 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5417
5418 return 0;
5419 }
5420}
5421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005422static int out_set_volume(struct audio_stream_out *stream, float left,
5423 float right)
5424{
Eric Laurenta9024de2013-04-04 09:19:12 -07005425 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005426 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305427 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005428
Arun Mirpuri5d170872019-03-26 13:21:31 -07005429 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005430 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5431 /* only take left channel into account: the API is for stereo anyway */
5432 out->muted = (left == 0.0f);
5433 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005434 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305435 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005436 /*
5437 * Set mute or umute on HDMI passthrough stream.
5438 * Only take left channel into account.
5439 * Mute is 0 and unmute 1
5440 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305441 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305442 } else if (out->format == AUDIO_FORMAT_DSD){
5443 char mixer_ctl_name[128] = "DSD Volume";
5444 struct audio_device *adev = out->dev;
5445 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5446
5447 if (!ctl) {
5448 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5449 __func__, mixer_ctl_name);
5450 return -EINVAL;
5451 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305452 volume[0] = (long)(AmpToDb(left));
5453 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305454 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5455 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005456 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005457 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005458 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5459 struct listnode *node = NULL;
5460 list_for_each(node, &adev->active_outputs_list) {
5461 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5462 streams_output_ctxt_t,
5463 list);
5464 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5465 out->volume_l = out_ctxt->output->volume_l;
5466 out->volume_r = out_ctxt->output->volume_r;
5467 }
5468 }
5469 if (!out->a2dp_compress_mute) {
5470 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5471 }
5472 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005473 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305474 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005475 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305476 if (!out->a2dp_compress_mute)
5477 ret = out_set_compr_volume(stream, left, right);
5478 out->volume_l = left;
5479 out->volume_r = right;
5480 pthread_mutex_unlock(&out->compr_mute_lock);
5481 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005482 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005483 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005484 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5485 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5486 if (!out->standby) {
5487 audio_extn_utils_send_app_type_gain(out->dev,
5488 out->app_type_cfg.app_type,
5489 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005490 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005491 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005492 out->volume_l = left;
5493 out->volume_r = right;
5494 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005495 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5496 ALOGV("%s: MMAP set volume called", __func__);
5497 if (!out->standby)
5498 ret = out_set_mmap_volume(stream, left, right);
5499 out->volume_l = left;
5500 out->volume_r = right;
5501 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305502 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305503 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5504 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305505 /* Volume control for pcm playback */
5506 if (!out->standby)
5507 ret = out_set_pcm_volume(stream, left, right);
5508 else
5509 out->apply_volume = true;
5510
5511 out->volume_l = left;
5512 out->volume_r = right;
5513 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005514 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5515 ALOGV("%s: bus device set volume called", __func__);
5516 if (!out->standby)
5517 ret = out_set_pcm_volume(stream, left, right);
5518 out->volume_l = left;
5519 out->volume_r = right;
5520 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005521 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005523 return -ENOSYS;
5524}
5525
Zhou Songc9672822017-08-16 16:01:39 +08005526static void update_frames_written(struct stream_out *out, size_t bytes)
5527{
5528 size_t bpf = 0;
5529
5530 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5531 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5532 bpf = 1;
5533 else if (!is_offload_usecase(out->usecase))
5534 bpf = audio_bytes_per_sample(out->format) *
5535 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005536
5537 pthread_mutex_lock(&out->position_query_lock);
5538 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005539 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005540 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5541 }
5542 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005543}
5544
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005545int split_and_write_audio_haptic_data(struct stream_out *out,
5546 const void *buffer, size_t bytes_to_write)
5547{
5548 struct audio_device *adev = out->dev;
5549
5550 int ret = 0;
5551 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5552 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5553 size_t frame_size = channel_count * bytes_per_sample;
5554 size_t frame_count = bytes_to_write / frame_size;
5555
5556 bool force_haptic_path =
5557 property_get_bool("vendor.audio.test_haptic", false);
5558
5559 // extract Haptics data from Audio buffer
5560 bool alloc_haptic_buffer = false;
5561 int haptic_channel_count = adev->haptics_config.channels;
5562 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5563 size_t audio_frame_size = frame_size - haptic_frame_size;
5564 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5565
5566 if (adev->haptic_buffer == NULL) {
5567 alloc_haptic_buffer = true;
5568 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5569 free(adev->haptic_buffer);
5570 adev->haptic_buffer_size = 0;
5571 alloc_haptic_buffer = true;
5572 }
5573
5574 if (alloc_haptic_buffer) {
5575 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005576 if(adev->haptic_buffer == NULL) {
5577 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5578 return -ENOMEM;
5579 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005580 adev->haptic_buffer_size = total_haptic_buffer_size;
5581 }
5582
5583 size_t src_index = 0, aud_index = 0, hap_index = 0;
5584 uint8_t *audio_buffer = (uint8_t *)buffer;
5585 uint8_t *haptic_buffer = adev->haptic_buffer;
5586
5587 // This is required for testing only. This works for stereo data only.
5588 // One channel is fed to audio stream and other to haptic stream for testing.
5589 if (force_haptic_path)
5590 audio_frame_size = haptic_frame_size = bytes_per_sample;
5591
5592 for (size_t i = 0; i < frame_count; i++) {
5593 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5594 audio_frame_size);
5595 aud_index += audio_frame_size;
5596 src_index += audio_frame_size;
5597
5598 if (adev->haptic_pcm)
5599 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5600 haptic_frame_size);
5601 hap_index += haptic_frame_size;
5602 src_index += haptic_frame_size;
5603
5604 // This is required for testing only.
5605 // Discard haptic channel data.
5606 if (force_haptic_path)
5607 src_index += haptic_frame_size;
5608 }
5609
5610 // write to audio pipeline
5611 ret = pcm_write(out->pcm, (void *)audio_buffer,
5612 frame_count * audio_frame_size);
5613
5614 // write to haptics pipeline
5615 if (adev->haptic_pcm)
5616 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5617 frame_count * haptic_frame_size);
5618
5619 return ret;
5620}
5621
Aalique Grahame22e49102018-12-18 14:23:57 -08005622#ifdef NO_AUDIO_OUT
5623static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5624 const void *buffer __unused, size_t bytes)
5625{
5626 struct stream_out *out = (struct stream_out *)stream;
5627
5628 /* No Output device supported other than BT for playback.
5629 * Sleep for the amount of buffer duration
5630 */
5631 lock_output_stream(out);
5632 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5633 (const struct audio_stream_out *)&out->stream) /
5634 out_get_sample_rate(&out->stream.common));
5635 pthread_mutex_unlock(&out->lock);
5636 return bytes;
5637}
5638#endif
5639
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005640static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5641 size_t bytes)
5642{
5643 struct stream_out *out = (struct stream_out *)stream;
5644 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005645 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305646 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005647 const size_t frame_size = audio_stream_out_frame_size(stream);
5648 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305649 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005650 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005651
Haynes Mathew George380745d2017-10-04 15:27:45 -07005652 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005653 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305654
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305655 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005656
Dhananjay Kumarac341582017-02-23 23:42:25 +05305657 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305658 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305659 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5660 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005661 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305662 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305663 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305664 ALOGD(" %s: sound card is not active/SSR state", __func__);
5665 ret= -EIO;
5666 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305667 }
5668 }
5669
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305670 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305671 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305672 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305673 goto exit;
5674 }
5675
Haynes Mathew George16081042017-05-31 17:16:49 -07005676 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5677 ret = -EINVAL;
5678 goto exit;
5679 }
5680
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005681 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305682 !out->is_iec61937_info_available) {
5683
5684 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5685 out->is_iec61937_info_available = true;
5686 } else if (audio_extn_passthru_is_enabled()) {
5687 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305688 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305689
5690 if((out->format == AUDIO_FORMAT_DTS) ||
5691 (out->format == AUDIO_FORMAT_DTS_HD)) {
5692 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5693 buffer, bytes);
5694 if (ret) {
5695 if (ret != -ENOSYS) {
5696 out->is_iec61937_info_available = false;
5697 ALOGD("iec61937 transmission info not yet updated retry");
5698 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305699 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305700 /* if stream has started and after that there is
5701 * stream config change (iec transmission config)
5702 * then trigger select_device to update backend configuration.
5703 */
5704 out->stream_config_changed = true;
5705 pthread_mutex_lock(&adev->lock);
5706 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305707 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005708 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305709 ret = -EINVAL;
5710 goto exit;
5711 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305712 pthread_mutex_unlock(&adev->lock);
5713 out->stream_config_changed = false;
5714 out->is_iec61937_info_available = true;
5715 }
5716 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305717
Meng Wang4c32fb42020-01-16 17:57:11 +08005718#ifdef AUDIO_GKI_ENABLED
5719 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5720 compr_passthr = out->compr_config.codec->reserved[0];
5721#else
5722 compr_passthr = out->compr_config.codec->compr_passthr;
5723#endif
5724
Garmond Leung317cbf12017-09-13 16:20:50 -07005725 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005726 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305727 (out->is_iec61937_info_available == true)) {
5728 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5729 ret = -EINVAL;
5730 goto exit;
5731 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305732 }
5733 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305734
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005735 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005736 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005737 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5738 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305739 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305740 ret = -EIO;
5741 goto exit;
5742 }
5743 }
5744 }
5745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005746 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005747 out->standby = false;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005748 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
5749
Eric Laurent150dbfe2013-02-27 14:31:02 -08005750 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005751 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5752 ret = voice_extn_compress_voip_start_output_stream(out);
5753 else
5754 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005755 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005756 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005757 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005758 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005759 goto exit;
5760 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305761 out->started = 1;
Andy Hunga1f48fa2019-07-01 18:14:53 -07005762 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
vivek mehtab72d08d2016-04-29 03:16:47 -07005763 if (last_known_cal_step != -1) {
5764 ALOGD("%s: retry previous failed cal level set", __func__);
5765 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305766 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005767 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305768
5769 if ((out->is_iec61937_info_available == true) &&
5770 (audio_extn_passthru_is_passthrough_stream(out))&&
5771 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5772 ret = -EINVAL;
5773 goto exit;
5774 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305775 if (out->set_dual_mono)
5776 audio_extn_send_dual_mono_mixing_coefficients(out);
Andy Hungc6bfd4a2019-07-01 18:26:00 -07005777
5778 // log startup time in ms.
5779 simple_stats_log(
5780 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005781 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005782
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005783 if (adev->is_channel_status_set == false &&
5784 compare_device_type(&out->device_list,
5785 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005786 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305787 adev->is_channel_status_set = true;
5788 }
5789
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305790 if ((adev->use_old_pspd_mix_ctrl == true) &&
5791 (out->pspd_coeff_sent == false)) {
5792 /*
5793 * Need to resend pspd coefficients after stream started for
5794 * older kernel version as it does not save the coefficients
5795 * and also stream has to be started for coeff to apply.
5796 */
5797 usecase = get_usecase_from_list(adev, out->usecase);
5798 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305799 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305800 out->pspd_coeff_sent = true;
5801 }
5802 }
5803
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005804 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005805 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005806 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005807 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005808 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5809 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305810 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5811 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005812 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305813 out->send_next_track_params = false;
5814 out->is_compr_metadata_avail = false;
5815 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005816 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305817 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305818 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005819
Ashish Jain83a6cc22016-06-28 14:34:17 +05305820 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305821 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305822 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305823 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005824 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305825 return -EINVAL;
5826 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305827 audio_format_t dst_format = out->hal_op_format;
5828 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305829
Dieter Luecking5d57def2018-09-07 14:23:37 +02005830 /* prevent division-by-zero */
5831 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5832 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5833 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5834 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305835 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005836 ATRACE_END();
5837 return -EINVAL;
5838 }
5839
Ashish Jainf1eaa582016-05-23 20:54:24 +05305840 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5841 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5842
Ashish Jain83a6cc22016-06-28 14:34:17 +05305843 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305844 dst_format,
5845 buffer,
5846 src_format,
5847 frames);
5848
Ashish Jain83a6cc22016-06-28 14:34:17 +05305849 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305850 bytes_to_write);
5851
5852 /*Convert written bytes in audio flinger format*/
5853 if (ret > 0)
5854 ret = ((ret * format_to_bitwidth_table[out->format]) /
5855 format_to_bitwidth_table[dst_format]);
5856 }
5857 } else
5858 ret = compress_write(out->compr, buffer, bytes);
5859
Zhou Songc9672822017-08-16 16:01:39 +08005860 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5861 update_frames_written(out, bytes);
5862
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305863 if (ret < 0)
5864 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005865 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305866 /*msg to cb thread only if non blocking write is enabled*/
5867 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305868 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005869 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305870 } else if (-ENETRESET == ret) {
5871 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305872 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305873 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305874 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005875 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305876 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005877 }
Ashish Jain5106d362016-05-11 19:23:33 +05305878
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305879 /* Call compr start only when non-zero bytes of data is there to be rendered */
5880 if (!out->playback_started && ret > 0) {
5881 int status = compress_start(out->compr);
5882 if (status < 0) {
5883 ret = status;
5884 ALOGE("%s: compr start failed with err %d", __func__, errno);
5885 goto exit;
5886 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005887 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005888 out->playback_started = 1;
5889 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005890
5891 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5892 popcount(out->channel_mask),
5893 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005894 }
5895 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005896 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005897 return ret;
5898 } else {
5899 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005900 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005901 if (out->muted)
5902 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005903 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5904 __func__, frames, frame_size, bytes_to_write);
5905
Aalique Grahame22e49102018-12-18 14:23:57 -08005906 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005907 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5908 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5909 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005910 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5911 int16_t *src = (int16_t *)buffer;
5912 int16_t *dst = (int16_t *)buffer;
5913
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005914 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005915 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005916 "out_write called for %s use case with wrong properties",
5917 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005918
5919 /*
5920 * FIXME: this can be removed once audio flinger mixer supports
5921 * mono output
5922 */
5923
5924 /*
5925 * Code below goes over each frame in the buffer and adds both
5926 * L and R samples and then divides by 2 to convert to mono
5927 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005928 if (channel_count == 2) {
5929 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5930 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5931 }
5932 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005933 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005934 }
Andy Hunga1f48fa2019-07-01 18:14:53 -07005935
5936 // Note: since out_get_presentation_position() is called alternating with out_write()
5937 // by AudioFlinger, we can check underruns using the prior timestamp read.
5938 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
5939 if (out->last_fifo_valid) {
5940 // compute drain to see if there is an underrun.
5941 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
5942 const int64_t frames_by_time =
5943 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
5944 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
5945
5946 if (underrun > 0) {
5947 simple_stats_log(&out->fifo_underruns, underrun);
5948
5949 ALOGW("%s: underrun(%lld) "
5950 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
5951 __func__,
5952 (long long)out->fifo_underruns.n,
5953 (long long)frames_by_time,
5954 (long long)out->last_fifo_frames_remaining);
5955 }
5956 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
5957 }
5958
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305959 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005960
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005961 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005962
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005963 if (out->config.rate)
5964 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5965 out->config.rate;
5966
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005967 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005968 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5969
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005970 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005971 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005972 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305973 out->convert_buffer != NULL) {
5974
5975 memcpy_by_audio_format(out->convert_buffer,
5976 out->hal_op_format,
5977 buffer,
5978 out->hal_ip_format,
5979 out->config.period_size * out->config.channels);
5980
5981 ret = pcm_write(out->pcm, out->convert_buffer,
5982 (out->config.period_size *
5983 out->config.channels *
5984 format_to_bitwidth_table[out->hal_op_format]));
5985 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305986 /*
5987 * To avoid underrun in DSP when the application is not pumping
5988 * data at required rate, check for the no. of bytes and ignore
5989 * pcm_write if it is less than actual buffer size.
5990 * It is a work around to a change in compress VOIP driver.
5991 */
5992 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5993 bytes < (out->config.period_size * out->config.channels *
5994 audio_bytes_per_sample(out->format))) {
5995 size_t voip_buf_size =
5996 out->config.period_size * out->config.channels *
5997 audio_bytes_per_sample(out->format);
5998 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5999 __func__, bytes, voip_buf_size);
6000 usleep(((uint64_t)voip_buf_size - bytes) *
6001 1000000 / audio_stream_out_frame_size(stream) /
6002 out_get_sample_rate(&out->stream.common));
6003 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006004 } else {
6005 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
6006 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
6007 else
6008 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
6009 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05306010 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006011
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006012 release_out_focus(out);
6013
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306014 if (ret < 0)
6015 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08006016 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05306017 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006018 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006019 }
6020
6021exit:
Zhou Songc9672822017-08-16 16:01:39 +08006022 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306023 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306024 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05306025 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006026 pthread_mutex_unlock(&out->lock);
6027
6028 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07006029 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08006030 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306031 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306032 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306033 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306034 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306035 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306036 out->standby = true;
6037 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306038 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02006039 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
6040 /* prevent division-by-zero */
6041 uint32_t stream_size = audio_stream_out_frame_size(stream);
6042 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006043
Dieter Luecking5d57def2018-09-07 14:23:37 +02006044 if ((stream_size == 0) || (srate == 0)) {
6045 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
6046 ATRACE_END();
6047 return -EINVAL;
6048 }
6049 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
6050 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006051 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05306052 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07006053 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07006054 return ret;
6055 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006056 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07006057 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006058 return bytes;
6059}
6060
6061static int out_get_render_position(const struct audio_stream_out *stream,
6062 uint32_t *dsp_frames)
6063{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006064 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08006065
6066 if (dsp_frames == NULL)
6067 return -EINVAL;
6068
6069 *dsp_frames = 0;
6070 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08006071 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05306072
6073 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
6074 * this operation and adev_close_output_stream(where out gets reset).
6075 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05306076 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006077 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306078 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006079 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306080 return 0;
6081 }
6082
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006083 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306084 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306085 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006086 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306087 if (ret < 0)
6088 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006089 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306090 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006091 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306092 if (-ENETRESET == ret) {
6093 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306094 out->card_status = CARD_STATUS_OFFLINE;
6095 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306096 } else if(ret < 0) {
6097 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306098 ret = -EINVAL;
6099 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306100 /*
6101 * Handle corner case where compress session is closed during SSR
6102 * and timestamp is queried
6103 */
6104 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306105 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306106 } else if (out->prev_card_status_offline) {
6107 ALOGE("ERROR: previously sound card was offline,return error");
6108 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306109 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306110 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006111 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306112 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306113 pthread_mutex_unlock(&out->lock);
6114 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006115 } else if (audio_is_linear_pcm(out->format)) {
6116 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006117 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006118 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006119 } else
6120 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006121}
6122
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006123static int out_add_audio_effect(const struct audio_stream *stream __unused,
6124 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006125{
6126 return 0;
6127}
6128
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006129static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6130 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006131{
6132 return 0;
6133}
6134
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006135static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6136 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006137{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306138 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006139}
6140
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006141static int out_get_presentation_position(const struct audio_stream_out *stream,
6142 uint64_t *frames, struct timespec *timestamp)
6143{
6144 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306145 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006146 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006147
Ashish Jain5106d362016-05-11 19:23:33 +05306148 /* below piece of code is not guarded against any lock because audioFliner serializes
6149 * this operation and adev_close_output_stream( where out gets reset).
6150 */
6151 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306152 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006153 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306154 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6155 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6156 return 0;
6157 }
6158
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006159 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006160
Ashish Jain5106d362016-05-11 19:23:33 +05306161 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6162 ret = compress_get_tstamp(out->compr, &dsp_frames,
6163 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006164 // Adjustment accounts for A2dp encoder latency with offload usecases
6165 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006166 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006167 unsigned long offset =
6168 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6169 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6170 }
Ashish Jain5106d362016-05-11 19:23:33 +05306171 ALOGVV("%s rendered frames %ld sample_rate %d",
6172 __func__, dsp_frames, out->sample_rate);
6173 *frames = dsp_frames;
6174 if (ret < 0)
6175 ret = -errno;
6176 if (-ENETRESET == ret) {
6177 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306178 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306179 ret = -EINVAL;
6180 } else
6181 ret = 0;
6182 /* this is the best we can do */
6183 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006184 } else {
6185 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006186 unsigned int avail;
6187 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
George Gao62ebc722019-07-29 16:29:44 -07006188 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006189 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006190
Andy Hunga1f48fa2019-07-01 18:14:53 -07006191 if (out->kernel_buffer_size > avail) {
6192 frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
6193 } else {
6194 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
6195 __func__, avail, out->kernel_buffer_size);
6196 avail = out->kernel_buffer_size;
6197 frames_temp = out->last_fifo_frames_remaining = 0;
6198 }
6199 out->last_fifo_valid = true;
6200 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
6201
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006202 if (out->written >= frames_temp)
6203 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006204
Andy Hunga1f48fa2019-07-01 18:14:53 -07006205 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
6206 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
6207
Weiyin Jiangd4633762018-03-16 12:05:03 +08006208 // This adjustment accounts for buffering after app processor.
6209 // It is based on estimated DSP latency per use case, rather than exact.
Robert Lee58215542019-07-15 20:55:12 +08006210 pthread_mutex_lock(&adev->lock);
6211 frames_temp = platform_render_latency(out->dev, out->usecase) *
6212 out->sample_rate / 1000000LL;
6213 pthread_mutex_unlock(&adev->lock);
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006214 if (signed_frames >= frames_temp)
6215 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006216
Weiyin Jiangd4633762018-03-16 12:05:03 +08006217 // Adjustment accounts for A2dp encoder latency with non offload usecases
6218 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006219 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006220 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6221 if (signed_frames >= frames_temp)
6222 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006223 }
6224
6225 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006226 *frames = signed_frames;
6227 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006228 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006229 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6230 // audioflinger still needs position updates when A2DP is suspended
Jasmine Cha5c2517f2019-09-09 11:07:28 +08006231 (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306232 *frames = out->written;
6233 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306234 if (is_offload_usecase(out->usecase))
6235 ret = -EINVAL;
6236 else
6237 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006238 }
6239 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006240 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006241 return ret;
6242}
6243
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006244static int out_set_callback(struct audio_stream_out *stream,
6245 stream_callback_t callback, void *cookie)
6246{
6247 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006248 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006249
6250 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006251 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006252 out->client_callback = callback;
6253 out->client_cookie = cookie;
6254 if (out->adsp_hdlr_stream_handle) {
6255 ret = audio_extn_adsp_hdlr_stream_set_callback(
6256 out->adsp_hdlr_stream_handle,
6257 callback,
6258 cookie);
6259 if (ret)
6260 ALOGW("%s:adsp hdlr callback registration failed %d",
6261 __func__, ret);
6262 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006263 pthread_mutex_unlock(&out->lock);
6264 return 0;
6265}
6266
6267static int out_pause(struct audio_stream_out* stream)
6268{
6269 struct stream_out *out = (struct stream_out *)stream;
6270 int status = -ENOSYS;
6271 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006272 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006273 ALOGD("copl(%p):pause compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306274 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006275 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006276 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306277 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306278 status = compress_pause(out->compr);
6279
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006280 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006281
Mingming Yin21854652016-04-13 11:54:02 -07006282 if (audio_extn_passthru_is_active()) {
6283 ALOGV("offload use case, pause passthru");
6284 audio_extn_passthru_on_pause(out);
6285 }
6286
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306287 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006288 audio_extn_dts_notify_playback_state(out->usecase, 0,
6289 out->sample_rate, popcount(out->channel_mask),
6290 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006291 }
6292 pthread_mutex_unlock(&out->lock);
6293 }
6294 return status;
6295}
6296
6297static int out_resume(struct audio_stream_out* stream)
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)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006303 ALOGD("copl(%p):resume compress driver", out);
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306304 status = -ENODATA;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006305 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006306 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306307 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306308 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006309 }
6310 if (!status) {
6311 out->offload_state = OFFLOAD_STATE_PLAYING;
6312 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306313 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006314 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6315 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006316 }
6317 pthread_mutex_unlock(&out->lock);
6318 }
6319 return status;
6320}
6321
6322static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6323{
6324 struct stream_out *out = (struct stream_out *)stream;
6325 int status = -ENOSYS;
6326 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006327 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006328 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006329 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6330 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6331 else
6332 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6333 pthread_mutex_unlock(&out->lock);
6334 }
6335 return status;
6336}
6337
6338static int out_flush(struct audio_stream_out* stream)
6339{
6340 struct stream_out *out = (struct stream_out *)stream;
6341 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006342 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006343 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006344 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006345 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6346 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006347 } else {
6348 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6349 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006350 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006351 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006352 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006353 return 0;
6354 }
6355 return -ENOSYS;
6356}
6357
Haynes Mathew George16081042017-05-31 17:16:49 -07006358static int out_stop(const struct audio_stream_out* stream)
6359{
6360 struct stream_out *out = (struct stream_out *)stream;
6361 struct audio_device *adev = out->dev;
6362 int ret = -ENOSYS;
6363
6364 ALOGV("%s", __func__);
6365 pthread_mutex_lock(&adev->lock);
6366 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6367 out->playback_started && out->pcm != NULL) {
6368 pcm_stop(out->pcm);
6369 ret = stop_output_stream(out);
6370 out->playback_started = false;
6371 }
6372 pthread_mutex_unlock(&adev->lock);
6373 return ret;
6374}
6375
6376static int out_start(const struct audio_stream_out* stream)
6377{
6378 struct stream_out *out = (struct stream_out *)stream;
6379 struct audio_device *adev = out->dev;
6380 int ret = -ENOSYS;
6381
6382 ALOGV("%s", __func__);
6383 pthread_mutex_lock(&adev->lock);
6384 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6385 !out->playback_started && out->pcm != NULL) {
6386 ret = start_output_stream(out);
6387 if (ret == 0) {
6388 out->playback_started = true;
6389 }
6390 }
6391 pthread_mutex_unlock(&adev->lock);
6392 return ret;
6393}
6394
6395/*
6396 * Modify config->period_count based on min_size_frames
6397 */
6398static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6399{
6400 int periodCountRequested = (min_size_frames + config->period_size - 1)
6401 / config->period_size;
6402 int periodCount = MMAP_PERIOD_COUNT_MIN;
6403
6404 ALOGV("%s original config.period_size = %d config.period_count = %d",
6405 __func__, config->period_size, config->period_count);
6406
6407 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6408 periodCount *= 2;
6409 }
6410 config->period_count = periodCount;
6411
6412 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6413}
6414
Phil Burkfe17efd2019-03-25 10:23:35 -07006415// Read offset for the positional timestamp from a persistent vendor property.
6416// This is to workaround apparent inaccuracies in the timing information that
6417// is used by the AAudio timing model. The inaccuracies can cause glitches.
6418static int64_t get_mmap_out_time_offset() {
6419 const int32_t kDefaultOffsetMicros = 0;
6420 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006421 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006422 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6423 return mmap_time_offset_micros * (int64_t)1000;
6424}
6425
Haynes Mathew George16081042017-05-31 17:16:49 -07006426static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6427 int32_t min_size_frames,
6428 struct audio_mmap_buffer_info *info)
6429{
6430 struct stream_out *out = (struct stream_out *)stream;
6431 struct audio_device *adev = out->dev;
6432 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006433 unsigned int offset1 = 0;
6434 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006435 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006436 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006437 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006438
Arun Mirpuri5d170872019-03-26 13:21:31 -07006439 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306440 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006441 pthread_mutex_lock(&adev->lock);
6442
Sharad Sanglec6f32552018-05-04 16:15:38 +05306443 if (CARD_STATUS_OFFLINE == out->card_status ||
6444 CARD_STATUS_OFFLINE == adev->card_status) {
6445 ALOGW("out->card_status or adev->card_status offline, try again");
6446 ret = -EIO;
6447 goto exit;
6448 }
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306449 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07006450 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6451 ret = -EINVAL;
6452 goto exit;
6453 }
6454 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6455 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6456 ret = -ENOSYS;
6457 goto exit;
6458 }
6459 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6460 if (out->pcm_device_id < 0) {
6461 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6462 __func__, out->pcm_device_id, out->usecase);
6463 ret = -EINVAL;
6464 goto exit;
6465 }
6466
6467 adjust_mmap_period_count(&out->config, min_size_frames);
6468
Arun Mirpuri5d170872019-03-26 13:21:31 -07006469 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006470 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6471 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6472 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306473 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306474 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6475 out->card_status = CARD_STATUS_OFFLINE;
6476 adev->card_status = CARD_STATUS_OFFLINE;
6477 ret = -EIO;
6478 goto exit;
6479 }
6480
Haynes Mathew George16081042017-05-31 17:16:49 -07006481 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6482 step = "open";
6483 ret = -ENODEV;
6484 goto exit;
6485 }
6486 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6487 if (ret < 0) {
6488 step = "begin";
6489 goto exit;
6490 }
juyuchen626833d2019-06-04 16:48:02 +08006491
6492 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006493 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006494 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006495 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006496 ret = platform_get_mmap_data_fd(adev->platform,
6497 out->pcm_device_id, 0 /*playback*/,
6498 &info->shared_memory_fd,
6499 &mmap_size);
6500 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006501 // Fall back to non exclusive mode
6502 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6503 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006504 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6505 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6506
Arun Mirpuri5d170872019-03-26 13:21:31 -07006507 if (mmap_size < buffer_size) {
6508 step = "mmap";
6509 goto exit;
6510 }
juyuchen626833d2019-06-04 16:48:02 +08006511 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006512 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006513 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006514 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006515
6516 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6517 if (ret < 0) {
6518 step = "commit";
6519 goto exit;
6520 }
6521
Phil Burkfe17efd2019-03-25 10:23:35 -07006522 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6523
Haynes Mathew George16081042017-05-31 17:16:49 -07006524 out->standby = false;
6525 ret = 0;
6526
Arun Mirpuri5d170872019-03-26 13:21:31 -07006527 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006528 __func__, info->shared_memory_address, info->buffer_size_frames);
6529
6530exit:
6531 if (ret != 0) {
6532 if (out->pcm == NULL) {
6533 ALOGE("%s: %s - %d", __func__, step, ret);
6534 } else {
6535 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6536 pcm_close(out->pcm);
6537 out->pcm = NULL;
6538 }
6539 }
6540 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306541 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006542 return ret;
6543}
6544
6545static int out_get_mmap_position(const struct audio_stream_out *stream,
6546 struct audio_mmap_position *position)
6547{
6548 struct stream_out *out = (struct stream_out *)stream;
6549 ALOGVV("%s", __func__);
6550 if (position == NULL) {
6551 return -EINVAL;
6552 }
6553 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006554 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006555 return -ENOSYS;
6556 }
6557 if (out->pcm == NULL) {
6558 return -ENOSYS;
6559 }
6560
6561 struct timespec ts = { 0, 0 };
6562 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6563 if (ret < 0) {
6564 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6565 return ret;
6566 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006567 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6568 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006569 return 0;
6570}
6571
6572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006573/** audio_stream_in implementation **/
6574static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6575{
6576 struct stream_in *in = (struct stream_in *)stream;
6577
6578 return in->config.rate;
6579}
6580
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006581static int in_set_sample_rate(struct audio_stream *stream __unused,
6582 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006583{
6584 return -ENOSYS;
6585}
6586
6587static size_t in_get_buffer_size(const struct audio_stream *stream)
6588{
6589 struct stream_in *in = (struct stream_in *)stream;
6590
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006591 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6592 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006593 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6594 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306595 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306596 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006597
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006598 return in->config.period_size * in->af_period_multiplier *
6599 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006600}
6601
6602static uint32_t in_get_channels(const struct audio_stream *stream)
6603{
6604 struct stream_in *in = (struct stream_in *)stream;
6605
6606 return in->channel_mask;
6607}
6608
6609static audio_format_t in_get_format(const struct audio_stream *stream)
6610{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006611 struct stream_in *in = (struct stream_in *)stream;
6612
6613 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006614}
6615
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006616static int in_set_format(struct audio_stream *stream __unused,
6617 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006618{
6619 return -ENOSYS;
6620}
6621
6622static int in_standby(struct audio_stream *stream)
6623{
6624 struct stream_in *in = (struct stream_in *)stream;
6625 struct audio_device *adev = in->dev;
6626 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306627 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6628 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006629 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306630
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006631 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006632 if (!in->standby && in->is_st_session) {
6633 ALOGD("%s: sound trigger pcm stop lab", __func__);
6634 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006635 if (adev->num_va_sessions > 0)
6636 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006637 in->standby = 1;
6638 }
6639
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006640 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006641 if (adev->adm_deregister_stream)
6642 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6643
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006644 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006645 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006646 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006647 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006648 voice_extn_compress_voip_close_input_stream(stream);
6649 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006650 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6651 do_stop = in->capture_started;
6652 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006653 if (in->mmap_shared_memory_fd >= 0) {
6654 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6655 __func__, in->mmap_shared_memory_fd);
6656 close(in->mmap_shared_memory_fd);
6657 in->mmap_shared_memory_fd = -1;
6658 }
Zhou Songa8895042016-07-05 17:54:22 +08006659 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306660 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306661 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006662 }
6663
Arun Mirpuri5d170872019-03-26 13:21:31 -07006664 if (in->pcm) {
6665 ATRACE_BEGIN("pcm_in_close");
6666 pcm_close(in->pcm);
6667 ATRACE_END();
6668 in->pcm = NULL;
6669 }
6670
Carter Hsu2e429db2019-05-14 18:50:52 +08006671 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006672 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006673
George Gao3018ede2019-10-23 13:23:00 -07006674 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6675 if (adev->num_va_sessions > 0)
6676 adev->num_va_sessions--;
6677 }
Quinn Malef6050362019-01-30 15:55:40 -08006678
Eric Laurent150dbfe2013-02-27 14:31:02 -08006679 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006680 }
6681 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006682 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006683 return status;
6684}
6685
Aalique Grahame22e49102018-12-18 14:23:57 -08006686static int in_dump(const struct audio_stream *stream,
6687 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006688{
Aalique Grahame22e49102018-12-18 14:23:57 -08006689 struct stream_in *in = (struct stream_in *)stream;
6690
6691 // We try to get the lock for consistency,
6692 // but it isn't necessary for these variables.
6693 // If we're not in standby, we may be blocked on a read.
6694 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6695 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6696 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6697 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6698
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006699 char buffer[256]; // for statistics formatting
6700 if (in->start_latency_ms.n > 0) {
6701 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
6702 dprintf(fd, " Start latency ms: %s\n", buffer);
6703 }
6704
Aalique Grahame22e49102018-12-18 14:23:57 -08006705 if (locked) {
6706 pthread_mutex_unlock(&in->lock);
6707 }
6708
6709 // dump error info
6710 (void)error_log_dump(
6711 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006713 return 0;
6714}
6715
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306716static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6717{
6718 if (!stream || !parms)
6719 return;
6720
6721 struct stream_in *in = (struct stream_in *)stream;
6722 struct audio_device *adev = in->dev;
6723
6724 card_status_t status;
6725 int card;
6726 if (parse_snd_card_status(parms, &card, &status) < 0)
6727 return;
6728
6729 pthread_mutex_lock(&adev->lock);
6730 bool valid_cb = (card == adev->snd_card);
6731 pthread_mutex_unlock(&adev->lock);
6732
6733 if (!valid_cb)
6734 return;
6735
6736 lock_input_stream(in);
6737 if (in->card_status != status)
6738 in->card_status = status;
6739 pthread_mutex_unlock(&in->lock);
6740
6741 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6742 use_case_table[in->usecase],
6743 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6744
6745 // a better solution would be to report error back to AF and let
6746 // it put the stream to standby
6747 if (status == CARD_STATUS_OFFLINE)
6748 in_standby(&in->stream.common);
6749
6750 return;
6751}
6752
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006753int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006754 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006755 audio_source_t source)
6756{
6757 struct audio_device *adev = in->dev;
6758 int ret = 0;
6759
6760 lock_input_stream(in);
6761 pthread_mutex_lock(&adev->lock);
6762
6763 /* no audio source uses val == 0 */
6764 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6765 in->source = source;
6766 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6767 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6768 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6769 (in->config.rate == 8000 || in->config.rate == 16000 ||
6770 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6771 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6772 ret = voice_extn_compress_voip_open_input_stream(in);
6773 if (ret != 0) {
6774 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6775 __func__, ret);
6776 }
6777 }
6778 }
6779
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006780 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6781 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006782 // Workaround: If routing to an non existing usb device, fail gracefully
6783 // The routing request will otherwise block during 10 second
6784 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006785 struct str_parms *usb_addr =
6786 str_parms_create_str(get_usb_device_address(devices));
6787 if (is_usb_in_device_type(devices) && usb_addr &&
6788 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006789 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6790 ret = -ENOSYS;
6791 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006792 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006793 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006794 if (!in->standby && !in->is_st_session) {
6795 ALOGV("update input routing change");
6796 // inform adm before actual routing to prevent glitches.
6797 if (adev->adm_on_routing_change) {
6798 adev->adm_on_routing_change(adev->adm_data,
6799 in->capture_handle);
6800 ret = select_devices(adev, in->usecase);
6801 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6802 adev->adm_routing_changed = true;
6803 }
6804 }
6805 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006806 if (usb_addr)
6807 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006808 }
6809 pthread_mutex_unlock(&adev->lock);
6810 pthread_mutex_unlock(&in->lock);
6811
6812 ALOGD("%s: exit: status(%d)", __func__, ret);
6813 return ret;
6814}
6815
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006816static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6817{
6818 struct stream_in *in = (struct stream_in *)stream;
6819 struct audio_device *adev = in->dev;
6820 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006821 char value[32];
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306822 int err = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006823
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306824 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006825 parms = str_parms_create_str(kvpairs);
6826
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306827 if (!parms)
6828 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006829 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006830 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006831
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306832 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6833 if (err >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306834 strlcpy(in->profile, value, sizeof(in->profile));
6835 ALOGV("updating stream profile with value '%s'", in->profile);
6836 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6837 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006838 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306839 in->sample_rate, in->bit_width,
6840 in->profile, &in->app_type_cfg);
6841 }
6842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006843 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006844 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006845
6846 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306847error:
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05306848 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006849}
6850
6851static char* in_get_parameters(const struct audio_stream *stream,
6852 const char *keys)
6853{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006854 struct stream_in *in = (struct stream_in *)stream;
6855 struct str_parms *query = str_parms_create_str(keys);
6856 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006857 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006858
6859 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006860 if (reply) {
6861 str_parms_destroy(reply);
6862 }
6863 if (query) {
6864 str_parms_destroy(query);
6865 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006866 ALOGE("in_get_parameters: failed to create query or reply");
6867 return NULL;
6868 }
6869
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006870 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006871
6872 voice_extn_in_get_parameters(in, query, reply);
6873
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006874 stream_get_parameter_channels(query, reply,
6875 &in->supported_channel_masks[0]);
6876 stream_get_parameter_formats(query, reply,
6877 &in->supported_formats[0]);
6878 stream_get_parameter_rates(query, reply,
6879 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006880 str = str_parms_to_str(reply);
6881 str_parms_destroy(query);
6882 str_parms_destroy(reply);
6883
6884 ALOGV("%s: exit: returns - %s", __func__, str);
6885 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006886}
6887
Aalique Grahame22e49102018-12-18 14:23:57 -08006888static int in_set_gain(struct audio_stream_in *stream,
6889 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006890{
Aalique Grahame22e49102018-12-18 14:23:57 -08006891 struct stream_in *in = (struct stream_in *)stream;
6892 char mixer_ctl_name[128];
6893 struct mixer_ctl *ctl;
6894 int ctl_value;
6895
6896 ALOGV("%s: gain %f", __func__, gain);
6897
6898 if (stream == NULL)
6899 return -EINVAL;
6900
6901 /* in_set_gain() only used to silence MMAP capture for now */
6902 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6903 return -ENOSYS;
6904
6905 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6906
6907 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6908 if (!ctl) {
6909 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6910 __func__, mixer_ctl_name);
6911 return -ENOSYS;
6912 }
6913
6914 if (gain < RECORD_GAIN_MIN)
6915 gain = RECORD_GAIN_MIN;
6916 else if (gain > RECORD_GAIN_MAX)
6917 gain = RECORD_GAIN_MAX;
6918 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6919
6920 mixer_ctl_set_value(ctl, 0, ctl_value);
6921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006922 return 0;
6923}
6924
6925static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6926 size_t bytes)
6927{
6928 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306929
6930 if (in == NULL) {
6931 ALOGE("%s: stream_in ptr is NULL", __func__);
6932 return -EINVAL;
6933 }
6934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006935 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306936 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306937 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006938
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006939 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306940
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006941 if (in->is_st_session) {
6942 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6943 /* Read from sound trigger HAL */
6944 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006945 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006946 if (adev->num_va_sessions < UINT_MAX)
6947 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006948 in->standby = 0;
6949 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006950 pthread_mutex_unlock(&in->lock);
6951 return bytes;
6952 }
6953
Haynes Mathew George16081042017-05-31 17:16:49 -07006954 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6955 ret = -ENOSYS;
6956 goto exit;
6957 }
6958
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006959 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6960 !in->standby && adev->adm_routing_changed) {
6961 ret = -ENOSYS;
6962 goto exit;
6963 }
6964
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006965 if (in->standby) {
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006966 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
6967
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006968 pthread_mutex_lock(&adev->lock);
6969 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6970 ret = voice_extn_compress_voip_start_input_stream(in);
6971 else
6972 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006973 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6974 if (adev->num_va_sessions < UINT_MAX)
6975 adev->num_va_sessions++;
6976 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006977 pthread_mutex_unlock(&adev->lock);
6978 if (ret != 0) {
6979 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006980 }
6981 in->standby = 0;
Andy Hungc6bfd4a2019-07-01 18:26:00 -07006982
6983 // log startup time in ms.
6984 simple_stats_log(
6985 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006986 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006987
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306988 /* Avoid read if capture_stopped is set */
6989 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6990 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6991 ret = -EINVAL;
6992 goto exit;
6993 }
6994
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006995 // what's the duration requested by the client?
6996 long ns = 0;
6997
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306998 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006999 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
7000 in->config.rate;
7001
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007002 ret = request_in_focus(in, ns);
7003 if (ret != 0)
7004 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007005 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007006
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307007 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307008 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
7009 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307010 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007011 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307012 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07007013 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007014 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007015 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07007016 } else if (audio_extn_ffv_get_stream() == in) {
7017 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307018 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07007019 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307020 /* data from DSP comes in 24_8 format, convert it to 8_24 */
7021 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
7022 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
7023 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307024 ret = -EINVAL;
7025 goto exit;
7026 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307027 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05307028 ret = -errno;
7029 }
7030 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307031 /* bytes read is always set to bytes for non compress usecases */
7032 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007033 }
7034
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007035 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07007036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007037 /*
Quinn Malef6050362019-01-30 15:55:40 -08007038 * Instead of writing zeroes here, we could trust the hardware to always
7039 * provide zeroes when muted. This is also muted with voice recognition
7040 * usecases so that other clients do not have access to voice recognition
7041 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007042 */
Quinn Malef6050362019-01-30 15:55:40 -08007043 if ((ret == 0 && voice_get_mic_mute(adev) &&
7044 !voice_is_in_call_rec_stream(in) &&
7045 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
7046 (adev->num_va_sessions &&
7047 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
7048 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
7049 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007050 memset(buffer, 0, bytes);
7051
7052exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05307053 frame_size = audio_stream_in_frame_size(stream);
7054 if (frame_size > 0)
7055 in->frames_read += bytes_read/frame_size;
7056
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07007057 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307058 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007059 pthread_mutex_unlock(&in->lock);
7060
7061 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307062 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307063 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307064 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307065 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05307066 in->standby = true;
7067 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05307068 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05307069 bytes_read = bytes;
7070 memset(buffer, 0, bytes);
7071 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007072 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07007073 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
7074 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07007075 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05307076 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05307077 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007078 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05307079 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007080}
7081
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007082static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007083{
7084 return 0;
7085}
7086
Aalique Grahame22e49102018-12-18 14:23:57 -08007087static int in_get_capture_position(const struct audio_stream_in *stream,
7088 int64_t *frames, int64_t *time)
7089{
7090 if (stream == NULL || frames == NULL || time == NULL) {
7091 return -EINVAL;
7092 }
7093 struct stream_in *in = (struct stream_in *)stream;
7094 int ret = -ENOSYS;
7095
7096 lock_input_stream(in);
7097 // note: ST sessions do not close the alsa pcm driver synchronously
7098 // on standby. Therefore, we may return an error even though the
7099 // pcm stream is still opened.
7100 if (in->standby) {
7101 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
7102 "%s stream in standby but pcm not NULL for non ST session", __func__);
7103 goto exit;
7104 }
7105 if (in->pcm) {
7106 struct timespec timestamp;
7107 unsigned int avail;
7108 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7109 *frames = in->frames_read + avail;
Robert Lee58215542019-07-15 20:55:12 +08007110 pthread_mutex_lock(&adev->lock);
7111 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec
7112 - platform_capture_latency(in->dev, in->usecase) * 1000LL;
7113 pthread_mutex_unlock(&adev->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08007114 ret = 0;
7115 }
7116 }
7117exit:
7118 pthread_mutex_unlock(&in->lock);
7119 return ret;
7120}
7121
Carter Hsu2e429db2019-05-14 18:50:52 +08007122static int in_update_effect_list(bool add, effect_handle_t effect,
7123 struct listnode *head)
7124{
7125 struct listnode *node;
7126 struct in_effect_list *elist = NULL;
7127 struct in_effect_list *target = NULL;
7128 int ret = 0;
7129
7130 if (!head)
7131 return ret;
7132
7133 list_for_each(node, head) {
7134 elist = node_to_item(node, struct in_effect_list, list);
7135 if (elist->handle == effect) {
7136 target = elist;
7137 break;
7138 }
7139 }
7140
7141 if (add) {
7142 if (target) {
7143 ALOGD("effect %p already exist", effect);
7144 return ret;
7145 }
7146
7147 target = (struct in_effect_list *)
7148 calloc(1, sizeof(struct in_effect_list));
7149
7150 if (!target) {
7151 ALOGE("%s:fail to allocate memory", __func__);
7152 return -ENOMEM;
7153 }
7154
7155 target->handle = effect;
7156 list_add_tail(head, &target->list);
7157 } else {
7158 if (target) {
7159 list_remove(&target->list);
7160 free(target);
7161 }
7162 }
7163
7164 return ret;
7165}
7166
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007167static int add_remove_audio_effect(const struct audio_stream *stream,
7168 effect_handle_t effect,
7169 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007170{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007171 struct stream_in *in = (struct stream_in *)stream;
7172 int status = 0;
7173 effect_descriptor_t desc;
7174
7175 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007176 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7177
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007178 if (status != 0)
7179 return status;
7180
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007181 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007182 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007183 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007184 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7185 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007186 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007187
7188 in_update_effect_list(enable, effect, &in->aec_list);
7189 enable = !list_empty(&in->aec_list);
7190 if (enable == in->enable_aec)
7191 goto exit;
7192
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007193 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007194 ALOGD("AEC enable %d", enable);
7195
Aalique Grahame22e49102018-12-18 14:23:57 -08007196 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7197 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7198 in->dev->enable_voicerx = enable;
7199 struct audio_usecase *usecase;
7200 struct listnode *node;
7201 list_for_each(node, &in->dev->usecase_list) {
7202 usecase = node_to_item(node, struct audio_usecase, list);
7203 if (usecase->type == PCM_PLAYBACK)
7204 select_devices(in->dev, usecase->id);
7205 }
7206 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007207 if (!in->standby) {
7208 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7209 select_devices(in->dev, in->usecase);
7210 }
7211
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007212 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007213 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7214
7215 in_update_effect_list(enable, effect, &in->ns_list);
7216 enable = !list_empty(&in->ns_list);
7217 if (enable == in->enable_ns)
7218 goto exit;
7219
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007220 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007221 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007222 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007223 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7224 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007225 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7226 select_devices(in->dev, in->usecase);
7227 } else
7228 select_devices(in->dev, in->usecase);
7229 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007230 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007231exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007232 pthread_mutex_unlock(&in->dev->lock);
7233 pthread_mutex_unlock(&in->lock);
7234
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007235 return 0;
7236}
7237
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007238static int in_add_audio_effect(const struct audio_stream *stream,
7239 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007240{
Eric Laurent994a6932013-07-17 11:51:42 -07007241 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007242 return add_remove_audio_effect(stream, effect, true);
7243}
7244
7245static int in_remove_audio_effect(const struct audio_stream *stream,
7246 effect_handle_t effect)
7247{
Eric Laurent994a6932013-07-17 11:51:42 -07007248 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007249 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007250}
7251
Derek Chenf939fb72018-11-13 13:34:41 -08007252streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7253 audio_io_handle_t input)
7254{
7255 struct listnode *node;
7256
7257 list_for_each(node, &dev->active_inputs_list) {
7258 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7259 streams_input_ctxt_t,
7260 list);
7261 if (in_ctxt->input->capture_handle == input) {
7262 return in_ctxt;
7263 }
7264 }
7265 return NULL;
7266}
7267
7268streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7269 audio_io_handle_t output)
7270{
7271 struct listnode *node;
7272
7273 list_for_each(node, &dev->active_outputs_list) {
7274 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7275 streams_output_ctxt_t,
7276 list);
7277 if (out_ctxt->output->handle == output) {
7278 return out_ctxt;
7279 }
7280 }
7281 return NULL;
7282}
7283
Haynes Mathew George16081042017-05-31 17:16:49 -07007284static int in_stop(const struct audio_stream_in* stream)
7285{
7286 struct stream_in *in = (struct stream_in *)stream;
7287 struct audio_device *adev = in->dev;
7288
7289 int ret = -ENOSYS;
7290 ALOGV("%s", __func__);
7291 pthread_mutex_lock(&adev->lock);
7292 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7293 in->capture_started && in->pcm != NULL) {
7294 pcm_stop(in->pcm);
7295 ret = stop_input_stream(in);
7296 in->capture_started = false;
7297 }
7298 pthread_mutex_unlock(&adev->lock);
7299 return ret;
7300}
7301
7302static int in_start(const struct audio_stream_in* stream)
7303{
7304 struct stream_in *in = (struct stream_in *)stream;
7305 struct audio_device *adev = in->dev;
7306 int ret = -ENOSYS;
7307
7308 ALOGV("%s in %p", __func__, in);
7309 pthread_mutex_lock(&adev->lock);
7310 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7311 !in->capture_started && in->pcm != NULL) {
7312 if (!in->capture_started) {
7313 ret = start_input_stream(in);
7314 if (ret == 0) {
7315 in->capture_started = true;
7316 }
7317 }
7318 }
7319 pthread_mutex_unlock(&adev->lock);
7320 return ret;
7321}
7322
Phil Burke0a86d12019-02-16 22:28:11 -08007323// Read offset for the positional timestamp from a persistent vendor property.
7324// This is to workaround apparent inaccuracies in the timing information that
7325// is used by the AAudio timing model. The inaccuracies can cause glitches.
7326static int64_t in_get_mmap_time_offset() {
7327 const int32_t kDefaultOffsetMicros = 0;
7328 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007329 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007330 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7331 return mmap_time_offset_micros * (int64_t)1000;
7332}
7333
Haynes Mathew George16081042017-05-31 17:16:49 -07007334static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7335 int32_t min_size_frames,
7336 struct audio_mmap_buffer_info *info)
7337{
7338 struct stream_in *in = (struct stream_in *)stream;
7339 struct audio_device *adev = in->dev;
7340 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007341 unsigned int offset1 = 0;
7342 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007343 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007344 uint32_t mmap_size = 0;
7345 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007346
7347 pthread_mutex_lock(&adev->lock);
7348 ALOGV("%s in %p", __func__, in);
7349
Sharad Sanglec6f32552018-05-04 16:15:38 +05307350 if (CARD_STATUS_OFFLINE == in->card_status||
7351 CARD_STATUS_OFFLINE == adev->card_status) {
7352 ALOGW("in->card_status or adev->card_status offline, try again");
7353 ret = -EIO;
7354 goto exit;
7355 }
7356
Sujin Panicker7c7b6f92020-04-03 12:57:55 +05307357 if (info == NULL || !(min_size_frames > 0 && min_size_frames < INT32_MAX)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07007358 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7359 ret = -EINVAL;
7360 goto exit;
7361 }
7362 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7363 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7364 ALOGV("%s in %p", __func__, in);
7365 ret = -ENOSYS;
7366 goto exit;
7367 }
7368 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7369 if (in->pcm_device_id < 0) {
7370 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7371 __func__, in->pcm_device_id, in->usecase);
7372 ret = -EINVAL;
7373 goto exit;
7374 }
7375
7376 adjust_mmap_period_count(&in->config, min_size_frames);
7377
7378 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7379 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7380 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7381 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307382 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307383 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7384 in->card_status = CARD_STATUS_OFFLINE;
7385 adev->card_status = CARD_STATUS_OFFLINE;
7386 ret = -EIO;
7387 goto exit;
7388 }
7389
Haynes Mathew George16081042017-05-31 17:16:49 -07007390 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7391 step = "open";
7392 ret = -ENODEV;
7393 goto exit;
7394 }
7395
7396 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7397 if (ret < 0) {
7398 step = "begin";
7399 goto exit;
7400 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007401
juyuchen626833d2019-06-04 16:48:02 +08007402 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007403 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7404 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7405 info->burst_size_frames = in->config.period_size;
7406 ret = platform_get_mmap_data_fd(adev->platform,
7407 in->pcm_device_id, 1 /*capture*/,
7408 &info->shared_memory_fd,
7409 &mmap_size);
7410 if (ret < 0) {
7411 // Fall back to non exclusive mode
7412 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7413 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007414 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7415 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7416
Arun Mirpuri5d170872019-03-26 13:21:31 -07007417 if (mmap_size < buffer_size) {
7418 step = "mmap";
7419 goto exit;
7420 }
juyuchen626833d2019-06-04 16:48:02 +08007421 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007422 }
7423
7424 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007425
7426 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7427 if (ret < 0) {
7428 step = "commit";
7429 goto exit;
7430 }
7431
Phil Burke0a86d12019-02-16 22:28:11 -08007432 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7433
Haynes Mathew George16081042017-05-31 17:16:49 -07007434 in->standby = false;
7435 ret = 0;
7436
7437 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7438 __func__, info->shared_memory_address, info->buffer_size_frames);
7439
7440exit:
7441 if (ret != 0) {
7442 if (in->pcm == NULL) {
7443 ALOGE("%s: %s - %d", __func__, step, ret);
7444 } else {
7445 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7446 pcm_close(in->pcm);
7447 in->pcm = NULL;
7448 }
7449 }
7450 pthread_mutex_unlock(&adev->lock);
7451 return ret;
7452}
7453
7454static int in_get_mmap_position(const struct audio_stream_in *stream,
7455 struct audio_mmap_position *position)
7456{
7457 struct stream_in *in = (struct stream_in *)stream;
7458 ALOGVV("%s", __func__);
7459 if (position == NULL) {
7460 return -EINVAL;
7461 }
7462 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7463 return -ENOSYS;
7464 }
7465 if (in->pcm == NULL) {
7466 return -ENOSYS;
7467 }
7468 struct timespec ts = { 0, 0 };
7469 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7470 if (ret < 0) {
7471 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7472 return ret;
7473 }
Phil Burke0a86d12019-02-16 22:28:11 -08007474 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7475 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007476 return 0;
7477}
7478
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307479static int in_get_active_microphones(const struct audio_stream_in *stream,
7480 struct audio_microphone_characteristic_t *mic_array,
7481 size_t *mic_count) {
7482 struct stream_in *in = (struct stream_in *)stream;
7483 struct audio_device *adev = in->dev;
7484 ALOGVV("%s", __func__);
7485
7486 lock_input_stream(in);
7487 pthread_mutex_lock(&adev->lock);
7488 int ret = platform_get_active_microphones(adev->platform,
7489 audio_channel_count_from_in_mask(in->channel_mask),
7490 in->usecase, mic_array, mic_count);
7491 pthread_mutex_unlock(&adev->lock);
7492 pthread_mutex_unlock(&in->lock);
7493
7494 return ret;
7495}
7496
7497static int adev_get_microphones(const struct audio_hw_device *dev,
7498 struct audio_microphone_characteristic_t *mic_array,
7499 size_t *mic_count) {
7500 struct audio_device *adev = (struct audio_device *)dev;
7501 ALOGVV("%s", __func__);
7502
7503 pthread_mutex_lock(&adev->lock);
7504 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7505 pthread_mutex_unlock(&adev->lock);
7506
7507 return ret;
7508}
juyuchendb308c22019-01-21 11:57:17 -07007509
7510static void in_update_sink_metadata(struct audio_stream_in *stream,
7511 const struct sink_metadata *sink_metadata) {
7512
7513 if (stream == NULL
7514 || sink_metadata == NULL
7515 || sink_metadata->tracks == NULL) {
7516 return;
7517 }
7518
7519 int error = 0;
7520 struct stream_in *in = (struct stream_in *)stream;
7521 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007522 struct listnode devices;
7523
7524 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007525
7526 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007527 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007528
7529 lock_input_stream(in);
7530 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007531 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007532
7533 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007534 && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007535 && adev->voice_tx_output != NULL) {
7536 /* Use the rx device from afe-proxy record to route voice call because
7537 there is no routing if tx device is on primary hal and rx device
7538 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007539 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007540
7541 if (!voice_is_call_state_active(adev)) {
7542 if (adev->mode == AUDIO_MODE_IN_CALL) {
7543 adev->current_call_output = adev->voice_tx_output;
7544 error = voice_start_call(adev);
7545 if (error != 0)
7546 ALOGE("%s: start voice call failed %d", __func__, error);
7547 }
7548 } else {
7549 adev->current_call_output = adev->voice_tx_output;
7550 voice_update_devices_for_all_voice_usecases(adev);
7551 }
7552 }
7553
7554 pthread_mutex_unlock(&adev->lock);
7555 pthread_mutex_unlock(&in->lock);
7556}
7557
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307558int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007559 audio_io_handle_t handle,
7560 audio_devices_t devices,
7561 audio_output_flags_t flags,
7562 struct audio_config *config,
7563 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007564 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007565{
7566 struct audio_device *adev = (struct audio_device *)dev;
7567 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307568 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007569 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007570 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307571 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007572 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7573 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7574 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7575 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007576 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007577 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7578 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007579 bool force_haptic_path =
7580 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007581 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007582
kunleizdff872d2018-08-20 14:40:33 +08007583 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007584 is_usb_dev = false;
7585 devices = AUDIO_DEVICE_OUT_SPEAKER;
7586 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7587 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007588 if (config->format == AUDIO_FORMAT_DEFAULT)
7589 config->format = AUDIO_FORMAT_PCM_16_BIT;
7590 if (config->sample_rate == 0)
7591 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7592 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7593 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007594 }
7595
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007596 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307597
Rahul Sharma99770982019-03-06 17:05:26 +05307598 pthread_mutex_lock(&adev->lock);
7599 if (out_get_stream(adev, handle) != NULL) {
7600 ALOGW("%s, output stream already opened", __func__);
7601 ret = -EEXIST;
7602 }
7603 pthread_mutex_unlock(&adev->lock);
7604 if (ret)
7605 return ret;
7606
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007607 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7608
Mingming Yin3a941d42016-02-17 18:08:05 -08007609 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007610 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7611 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307612
7613
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007614 if (!out) {
7615 return -ENOMEM;
7616 }
7617
Haynes Mathew George204045b2015-02-25 20:32:03 -08007618 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007619 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307620 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007621 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007622 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007624 if (devices == AUDIO_DEVICE_NONE)
7625 devices = AUDIO_DEVICE_OUT_SPEAKER;
7626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007627 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007628 list_init(&out->device_list);
7629 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007630 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007631 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007632 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307633 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307634 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7635 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7636 else
7637 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007638 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007639 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007640 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307641 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307642 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307643 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007644 out->hal_output_suspend_supported = 0;
7645 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307646 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307647 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307648 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007649 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007650
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307651 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307652 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007653 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7654
Aalique Grahame22e49102018-12-18 14:23:57 -08007655 if (direct_dev &&
7656 (audio_is_linear_pcm(out->format) ||
7657 config->format == AUDIO_FORMAT_DEFAULT) &&
7658 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7659 audio_format_t req_format = config->format;
7660 audio_channel_mask_t req_channel_mask = config->channel_mask;
7661 uint32_t req_sample_rate = config->sample_rate;
7662
7663 pthread_mutex_lock(&adev->lock);
7664 if (is_hdmi) {
7665 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7666 ret = read_hdmi_sink_caps(out);
7667 if (config->sample_rate == 0)
7668 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7669 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7670 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7671 if (config->format == AUDIO_FORMAT_DEFAULT)
7672 config->format = AUDIO_FORMAT_PCM_16_BIT;
7673 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007674 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7675 &config->format,
7676 &out->supported_formats[0],
7677 MAX_SUPPORTED_FORMATS,
7678 &config->channel_mask,
7679 &out->supported_channel_masks[0],
7680 MAX_SUPPORTED_CHANNEL_MASKS,
7681 &config->sample_rate,
7682 &out->supported_sample_rates[0],
7683 MAX_SUPPORTED_SAMPLE_RATES);
7684 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007685 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007686
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007687 pthread_mutex_unlock(&adev->lock);
7688 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007689 if (ret == -ENOSYS) {
7690 /* ignore and go with default */
7691 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007692 }
7693 // For MMAP NO IRQ, allow conversions in ADSP
7694 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7695 goto error_open;
7696 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007697 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007698 goto error_open;
7699 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007700
7701 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7702 config->sample_rate = req_sample_rate;
7703 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7704 config->channel_mask = req_channel_mask;
7705 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7706 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007707 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007708
7709 out->sample_rate = config->sample_rate;
7710 out->channel_mask = config->channel_mask;
7711 out->format = config->format;
7712 if (is_hdmi) {
7713 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7714 out->config = pcm_config_hdmi_multi;
7715 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7716 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7717 out->config = pcm_config_mmap_playback;
7718 out->stream.start = out_start;
7719 out->stream.stop = out_stop;
7720 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7721 out->stream.get_mmap_position = out_get_mmap_position;
7722 } else {
7723 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7724 out->config = pcm_config_hifi;
7725 }
7726
7727 out->config.rate = out->sample_rate;
7728 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7729 if (is_hdmi) {
7730 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7731 audio_bytes_per_sample(out->format));
7732 }
7733 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007734 }
7735
Derek Chenf6318be2017-06-12 17:16:24 -04007736 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007737 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007738 /* extract car audio stream index */
7739 out->car_audio_stream =
7740 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7741 if (out->car_audio_stream < 0) {
7742 ALOGE("%s: invalid car audio stream %x",
7743 __func__, out->car_audio_stream);
7744 ret = -EINVAL;
7745 goto error_open;
7746 }
Derek Chen5f67a942020-02-24 23:08:13 -08007747 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007748 }
7749
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007750 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007751 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007752 if (!voice_extn_is_compress_voip_supported()) {
7753 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7754 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007755 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7756 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007757 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7758 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007759 out->volume_l = INVALID_OUT_VOLUME;
7760 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007761
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007762 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007763 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007764 uint32_t channel_count =
7765 audio_channel_count_from_out_mask(out->channel_mask);
7766 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7767 out->sample_rate, out->format,
7768 channel_count, false);
7769 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7770 if (frame_size != 0)
7771 out->config.period_size = buffer_size / frame_size;
7772 else
7773 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007774 }
7775 } else {
7776 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7777 voice_extn_compress_voip_is_active(out->dev)) &&
7778 (voice_extn_compress_voip_is_config_supported(config))) {
7779 ret = voice_extn_compress_voip_open_output_stream(out);
7780 if (ret != 0) {
7781 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7782 __func__, ret);
7783 goto error_open;
7784 }
Sujin Panicker19027262019-09-16 18:28:06 +05307785 } else {
7786 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7787 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007788 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007789 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007790 } else if (audio_is_linear_pcm(out->format) &&
7791 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7792 out->channel_mask = config->channel_mask;
7793 out->sample_rate = config->sample_rate;
7794 out->format = config->format;
7795 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7796 // does this change?
7797 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7798 out->config.rate = config->sample_rate;
7799 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7800 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7801 audio_bytes_per_sample(config->format));
7802 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007803 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307804 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307805 pthread_mutex_lock(&adev->lock);
7806 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7807 pthread_mutex_unlock(&adev->lock);
7808
7809 // reject offload during card offline to allow
7810 // fallback to s/w paths
7811 if (offline) {
7812 ret = -ENODEV;
7813 goto error_open;
7814 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007815
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007816 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7817 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7818 ALOGE("%s: Unsupported Offload information", __func__);
7819 ret = -EINVAL;
7820 goto error_open;
7821 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007822
Atul Khare3fa6e542017-08-09 00:56:17 +05307823 if (config->offload_info.format == 0)
7824 config->offload_info.format = config->format;
7825 if (config->offload_info.sample_rate == 0)
7826 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007827
Mingming Yin90310102013-11-13 16:57:00 -08007828 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307829 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007830 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007831 ret = -EINVAL;
7832 goto error_open;
7833 }
7834
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007835 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7836 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7837 (audio_extn_passthru_is_passthrough_stream(out)) &&
7838 !((config->sample_rate == 48000) ||
7839 (config->sample_rate == 96000) ||
7840 (config->sample_rate == 192000))) {
7841 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7842 __func__, config->sample_rate, config->offload_info.format);
7843 ret = -EINVAL;
7844 goto error_open;
7845 }
7846
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007847 out->compr_config.codec = (struct snd_codec *)
7848 calloc(1, sizeof(struct snd_codec));
7849
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007850 if (!out->compr_config.codec) {
7851 ret = -ENOMEM;
7852 goto error_open;
7853 }
7854
Dhananjay Kumarac341582017-02-23 23:42:25 +05307855 out->stream.pause = out_pause;
7856 out->stream.resume = out_resume;
7857 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307858 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307859 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007860 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307861 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007862 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307863 } else {
7864 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7865 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007866 }
vivek mehta446c3962015-09-14 10:57:35 -07007867
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307868 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7869 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007870#ifdef AUDIO_GKI_ENABLED
7871 /* out->compr_config.codec->reserved[1] is for flags */
7872 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7873#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307874 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007875#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307876 }
7877
vivek mehta446c3962015-09-14 10:57:35 -07007878 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007879 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007880 config->format == 0 && config->sample_rate == 0 &&
7881 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007882 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007883 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7884 } else {
7885 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7886 ret = -EEXIST;
7887 goto error_open;
7888 }
vivek mehta446c3962015-09-14 10:57:35 -07007889 }
7890
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007891 if (config->offload_info.channel_mask)
7892 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007893 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007894 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007895 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007896 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307897 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007898 ret = -EINVAL;
7899 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007900 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007901
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007902 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007903 out->sample_rate = config->offload_info.sample_rate;
7904
Mingming Yin3ee55c62014-08-04 14:23:35 -07007905 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007906
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307907 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307908 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307909 audio_extn_dolby_send_ddp_endp_params(adev);
7910 audio_extn_dolby_set_dmid(adev);
7911 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007912
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007913 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007914 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007915 out->compr_config.codec->bit_rate =
7916 config->offload_info.bit_rate;
7917 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307918 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007919 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307920 /* Update bit width only for non passthrough usecases.
7921 * For passthrough usecases, the output will always be opened @16 bit
7922 */
7923 if (!audio_extn_passthru_is_passthrough_stream(out))
7924 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307925
7926 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007927#ifdef AUDIO_GKI_ENABLED
7928 /* out->compr_config.codec->reserved[1] is for flags */
7929 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7930 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7931#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307932 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7933 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007934#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307935
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007936 /*TODO: Do we need to change it for passthrough */
7937 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007938
Manish Dewangana6fc5442015-08-24 20:30:31 +05307939 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7940 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307941 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307942 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307943 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7944 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307945
7946 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7947 AUDIO_FORMAT_PCM) {
7948
7949 /*Based on platform support, configure appropriate alsa format for corresponding
7950 *hal input format.
7951 */
7952 out->compr_config.codec->format = hal_format_to_alsa(
7953 config->offload_info.format);
7954
Ashish Jain83a6cc22016-06-28 14:34:17 +05307955 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307956 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307957 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307958
Dhananjay Kumarac341582017-02-23 23:42:25 +05307959 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307960 *hal input format and alsa format might differ based on platform support.
7961 */
7962 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307963 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307964
7965 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7966
Deeraj Soman93155a62019-09-30 19:00:37 +05307967 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7968 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7969 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7970 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7971 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307972
Ashish Jainf1eaa582016-05-23 20:54:24 +05307973 /* Check if alsa session is configured with the same format as HAL input format,
7974 * if not then derive correct fragment size needed to accomodate the
7975 * conversion of HAL input format to alsa format.
7976 */
7977 audio_extn_utils_update_direct_pcm_fragment_size(out);
7978
7979 /*if hal input and output fragment size is different this indicates HAL input format is
7980 *not same as the alsa format
7981 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307982 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307983 /*Allocate a buffer to convert input data to the alsa configured format.
7984 *size of convert buffer is equal to the size required to hold one fragment size
7985 *worth of pcm data, this is because flinger does not write more than fragment_size
7986 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307987 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7988 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307989 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7990 ret = -ENOMEM;
7991 goto error_open;
7992 }
7993 }
7994 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7995 out->compr_config.fragment_size =
7996 audio_extn_passthru_get_buffer_size(&config->offload_info);
7997 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7998 } else {
7999 out->compr_config.fragment_size =
8000 platform_get_compress_offload_buffer_size(&config->offload_info);
8001 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
8002 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07008003
Naresh Tanniruee3499a2017-01-05 14:05:35 +05308004 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8005 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
8006 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07008007 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05308008 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07008009
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05308010 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
8011 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
8012 }
8013
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008014 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
8015 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008016
Manish Dewangan69426c82017-01-30 17:35:36 +05308017 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
8018 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
8019 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
8020 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
8021 out->render_mode = RENDER_MODE_AUDIO_MASTER;
8022 } else {
8023 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
8024 }
Alexy Josephaa54c872014-12-03 02:46:47 -08008025
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05308026 memset(&out->channel_map_param, 0,
8027 sizeof(struct audio_out_channel_map_param));
8028
Haynes Mathew George352f27b2013-07-26 00:00:15 -07008029 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05308030 out->send_next_track_params = false;
8031 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008032 out->offload_state = OFFLOAD_STATE_IDLE;
8033 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08008034 out->writeAt.tv_sec = 0;
8035 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08008036
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008037 audio_extn_dts_create_state_notifier_node(out->usecase);
8038
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008039 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
8040 __func__, config->offload_info.version,
8041 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05308042
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308043 /* Check if DSD audio format is supported in codec
8044 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308045 */
8046
8047 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308048 (!platform_check_codec_dsd_support(adev->platform) ||
8049 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308050 ret = -EINVAL;
8051 goto error_open;
8052 }
8053
Ashish Jain5106d362016-05-11 19:23:33 +05308054 /* Disable gapless if any of the following is true
8055 * passthrough playback
8056 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05308057 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05308058 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308059 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308060 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07008061 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05308062 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05308063 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05308064 check_and_set_gapless_mode(adev, false);
8065 } else
8066 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07008067
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05308068 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07008069 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
8070 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308071 if (config->format == AUDIO_FORMAT_DSD) {
8072 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08008073#ifdef AUDIO_GKI_ENABLED
8074 /* out->compr_config.codec->reserved[0] is for compr_passthr */
8075 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
8076#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308077 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08008078#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05308079 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07008080
8081 create_offload_callback_thread(out);
8082
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008083 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008084 switch (config->sample_rate) {
8085 case 0:
8086 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8087 break;
8088 case 8000:
8089 case 16000:
8090 case 48000:
8091 out->sample_rate = config->sample_rate;
8092 break;
8093 default:
8094 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
8095 config->sample_rate);
8096 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8097 ret = -EINVAL;
8098 goto error_open;
8099 }
8100 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8101 switch (config->channel_mask) {
8102 case AUDIO_CHANNEL_NONE:
8103 case AUDIO_CHANNEL_OUT_STEREO:
8104 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8105 break;
8106 default:
8107 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8108 config->channel_mask);
8109 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8110 ret = -EINVAL;
8111 goto error_open;
8112 }
8113 switch (config->format) {
8114 case AUDIO_FORMAT_DEFAULT:
8115 case AUDIO_FORMAT_PCM_16_BIT:
8116 out->format = AUDIO_FORMAT_PCM_16_BIT;
8117 break;
8118 default:
8119 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8120 config->format);
8121 config->format = AUDIO_FORMAT_PCM_16_BIT;
8122 ret = -EINVAL;
8123 goto error_open;
8124 }
8125
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308126 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008127 if (ret != 0) {
8128 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008129 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008130 goto error_open;
8131 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008132 } else if (is_single_device_type_equal(&out->device_list,
8133 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008134 switch (config->sample_rate) {
8135 case 0:
8136 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8137 break;
8138 case 8000:
8139 case 16000:
8140 case 48000:
8141 out->sample_rate = config->sample_rate;
8142 break;
8143 default:
8144 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8145 config->sample_rate);
8146 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8147 ret = -EINVAL;
8148 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008149 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008150 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8151 switch (config->channel_mask) {
8152 case AUDIO_CHANNEL_NONE:
8153 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8154 break;
8155 case AUDIO_CHANNEL_OUT_STEREO:
8156 out->channel_mask = config->channel_mask;
8157 break;
8158 default:
8159 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8160 config->channel_mask);
8161 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8162 ret = -EINVAL;
8163 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008164 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008165 switch (config->format) {
8166 case AUDIO_FORMAT_DEFAULT:
8167 out->format = AUDIO_FORMAT_PCM_16_BIT;
8168 break;
8169 case AUDIO_FORMAT_PCM_16_BIT:
8170 out->format = config->format;
8171 break;
8172 default:
8173 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8174 config->format);
8175 config->format = AUDIO_FORMAT_PCM_16_BIT;
8176 ret = -EINVAL;
8177 break;
8178 }
8179 if (ret != 0)
8180 goto error_open;
8181
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008182 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8183 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008184 out->config.rate = out->sample_rate;
8185 out->config.channels =
8186 audio_channel_count_from_out_mask(out->channel_mask);
8187 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008188 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008189 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308190 unsigned int channels = 0;
8191 /*Update config params to default if not set by the caller*/
8192 if (config->sample_rate == 0)
8193 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8194 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8195 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8196 if (config->format == AUDIO_FORMAT_DEFAULT)
8197 config->format = AUDIO_FORMAT_PCM_16_BIT;
8198
8199 channels = audio_channel_count_from_out_mask(out->channel_mask);
8200
Varun Balaraje49253e2017-07-06 19:48:56 +05308201 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8202 out->usecase = get_interactive_usecase(adev);
8203 out->config = pcm_config_low_latency;
8204 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308205 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008206 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8207 out->flags);
8208 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008209 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8210 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8211 out->config = pcm_config_mmap_playback;
8212 out->stream.start = out_start;
8213 out->stream.stop = out_stop;
8214 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8215 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308216 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8217 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008218 out->hal_output_suspend_supported =
8219 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8220 out->dynamic_pm_qos_config_supported =
8221 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8222 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008223 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8224 } else {
8225 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8226 //the mixer path will be a string similar to "low-latency-playback resume"
8227 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8228 strlcat(out->pm_qos_mixer_path,
8229 " resume", MAX_MIXER_PATH_LEN);
8230 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8231 out->pm_qos_mixer_path);
8232 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308233 out->config = pcm_config_low_latency;
8234 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8235 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8236 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308237 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8238 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8239 if (out->config.period_size <= 0) {
8240 ALOGE("Invalid configuration period size is not valid");
8241 ret = -EINVAL;
8242 goto error_open;
8243 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008244 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8245 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8246 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008247 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8248 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8249 out->config = pcm_config_haptics_audio;
8250 if (force_haptic_path)
8251 adev->haptics_config = pcm_config_haptics_audio;
8252 else
8253 adev->haptics_config = pcm_config_haptics;
8254
Meng Wangd08ce322020-04-02 08:59:20 +08008255 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008256 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8257
8258 if (force_haptic_path) {
8259 out->config.channels = 1;
8260 adev->haptics_config.channels = 1;
8261 } else
8262 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 -08008263 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008264 ret = audio_extn_auto_hal_open_output_stream(out);
8265 if (ret) {
8266 ALOGE("%s: Failed to open output stream for bus device", __func__);
8267 ret = -EINVAL;
8268 goto error_open;
8269 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308270 } else {
8271 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008272 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8273 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308274 }
8275 out->hal_ip_format = format = out->format;
8276 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8277 out->hal_op_format = pcm_format_to_hal(out->config.format);
8278 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8279 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008280 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308281 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308282 if (out->hal_ip_format != out->hal_op_format) {
8283 uint32_t buffer_size = out->config.period_size *
8284 format_to_bitwidth_table[out->hal_op_format] *
8285 out->config.channels;
8286 out->convert_buffer = calloc(1, buffer_size);
8287 if (out->convert_buffer == NULL){
8288 ALOGE("Allocation failed for convert buffer for size %d",
8289 out->compr_config.fragment_size);
8290 ret = -ENOMEM;
8291 goto error_open;
8292 }
8293 ALOGD("Convert buffer allocated of size %d", buffer_size);
8294 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008295 }
8296
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008297 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8298 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308299
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008300 /* TODO remove this hardcoding and check why width is zero*/
8301 if (out->bit_width == 0)
8302 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308303 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008304 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008305 &out->device_list, out->flags,
8306 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308307 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308308 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008309 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008310 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8311 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008312 if(adev->primary_output == NULL)
8313 adev->primary_output = out;
8314 else {
8315 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008316 ret = -EEXIST;
8317 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008318 }
8319 }
8320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008321 /* Check if this usecase is already existing */
8322 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008323 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8324 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008325 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008326 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008327 ret = -EEXIST;
8328 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008329 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008331 pthread_mutex_unlock(&adev->lock);
8332
8333 out->stream.common.get_sample_rate = out_get_sample_rate;
8334 out->stream.common.set_sample_rate = out_set_sample_rate;
8335 out->stream.common.get_buffer_size = out_get_buffer_size;
8336 out->stream.common.get_channels = out_get_channels;
8337 out->stream.common.get_format = out_get_format;
8338 out->stream.common.set_format = out_set_format;
8339 out->stream.common.standby = out_standby;
8340 out->stream.common.dump = out_dump;
8341 out->stream.common.set_parameters = out_set_parameters;
8342 out->stream.common.get_parameters = out_get_parameters;
8343 out->stream.common.add_audio_effect = out_add_audio_effect;
8344 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8345 out->stream.get_latency = out_get_latency;
8346 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008347#ifdef NO_AUDIO_OUT
8348 out->stream.write = out_write_for_no_output;
8349#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008350 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008351#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008352 out->stream.get_render_position = out_get_render_position;
8353 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008354 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008355
Haynes Mathew George16081042017-05-31 17:16:49 -07008356 if (out->realtime)
8357 out->af_period_multiplier = af_period_multiplier;
8358 else
8359 out->af_period_multiplier = 1;
8360
Andy Hunga1f48fa2019-07-01 18:14:53 -07008361 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
8362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008363 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008364 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008365 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008366
8367 config->format = out->stream.common.get_format(&out->stream.common);
8368 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8369 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308370 register_format(out->format, out->supported_formats);
8371 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8372 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008373
Aalique Grahame22e49102018-12-18 14:23:57 -08008374 out->error_log = error_log_create(
8375 ERROR_LOG_ENTRIES,
8376 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8377
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308378 /*
8379 By locking output stream before registering, we allow the callback
8380 to update stream's state only after stream's initial state is set to
8381 adev state.
8382 */
8383 lock_output_stream(out);
8384 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8385 pthread_mutex_lock(&adev->lock);
8386 out->card_status = adev->card_status;
8387 pthread_mutex_unlock(&adev->lock);
8388 pthread_mutex_unlock(&out->lock);
8389
Aalique Grahame22e49102018-12-18 14:23:57 -08008390 stream_app_type_cfg_init(&out->app_type_cfg);
8391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008392 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308393 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008394 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008395
8396 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8397 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8398 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008399 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308400 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008401 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008402 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308403 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8404 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008405 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8406 out->usecase, PCM_PLAYBACK);
8407 hdlr_stream_cfg.flags = out->flags;
8408 hdlr_stream_cfg.type = PCM_PLAYBACK;
8409 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8410 &hdlr_stream_cfg);
8411 if (ret) {
8412 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8413 out->adsp_hdlr_stream_handle = NULL;
8414 }
8415 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308416 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8417 is_direct_passthough, false);
8418 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8419 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008420 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008421 if (ret < 0) {
8422 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8423 out->ip_hdlr_handle = NULL;
8424 }
8425 }
Derek Chenf939fb72018-11-13 13:34:41 -08008426
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008427 ret = io_streams_map_insert(adev, &out->stream.common,
8428 out->handle, AUDIO_PATCH_HANDLE_NONE);
8429 if (ret != 0)
8430 goto error_open;
8431
Derek Chenf939fb72018-11-13 13:34:41 -08008432 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8433 calloc(1, sizeof(streams_output_ctxt_t));
8434 if (out_ctxt == NULL) {
8435 ALOGE("%s fail to allocate output ctxt", __func__);
8436 ret = -ENOMEM;
8437 goto error_open;
8438 }
8439 out_ctxt->output = out;
8440
8441 pthread_mutex_lock(&adev->lock);
8442 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8443 pthread_mutex_unlock(&adev->lock);
8444
Eric Laurent994a6932013-07-17 11:51:42 -07008445 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008446 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008447
8448error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308449 if (out->convert_buffer)
8450 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008451 free(out);
8452 *stream_out = NULL;
8453 ALOGD("%s: exit: ret %d", __func__, ret);
8454 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008455}
8456
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308457void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008458 struct audio_stream_out *stream)
8459{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008460 struct stream_out *out = (struct stream_out *)stream;
8461 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008462 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008463
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008464 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308465
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008466 io_streams_map_remove(adev, out->handle);
8467
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308468 // must deregister from sndmonitor first to prevent races
8469 // between the callback and close_stream
8470 audio_extn_snd_mon_unregister_listener(out);
8471
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008472 /* close adsp hdrl session before standby */
8473 if (out->adsp_hdlr_stream_handle) {
8474 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8475 if (ret)
8476 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8477 out->adsp_hdlr_stream_handle = NULL;
8478 }
8479
Manish Dewangan21a850a2017-08-14 12:03:55 +05308480 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008481 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8482 out->ip_hdlr_handle = NULL;
8483 }
8484
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008485 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308486 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008487 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308488 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308489 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008490 if(ret != 0)
8491 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8492 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008493 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008494 out_standby(&stream->common);
8495
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008496 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008497 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008498 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008499 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008500 if (out->compr_config.codec != NULL)
8501 free(out->compr_config.codec);
8502 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008503
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308504 out->a2dp_compress_mute = false;
8505
Varun Balaraje49253e2017-07-06 19:48:56 +05308506 if (is_interactive_usecase(out->usecase))
8507 free_interactive_usecase(adev, out->usecase);
8508
Ashish Jain83a6cc22016-06-28 14:34:17 +05308509 if (out->convert_buffer != NULL) {
8510 free(out->convert_buffer);
8511 out->convert_buffer = NULL;
8512 }
8513
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008514 if (adev->voice_tx_output == out)
8515 adev->voice_tx_output = NULL;
8516
Aalique Grahame22e49102018-12-18 14:23:57 -08008517 error_log_destroy(out->error_log);
8518 out->error_log = NULL;
8519
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308520 if (adev->primary_output == out)
8521 adev->primary_output = NULL;
8522
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008523 pthread_cond_destroy(&out->cond);
8524 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008525
8526 pthread_mutex_lock(&adev->lock);
8527 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8528 if (out_ctxt != NULL) {
8529 list_remove(&out_ctxt->list);
8530 free(out_ctxt);
8531 } else {
8532 ALOGW("%s, output stream already closed", __func__);
8533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008534 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008535 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008536 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008537}
8538
8539static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8540{
8541 struct audio_device *adev = (struct audio_device *)dev;
8542 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008543 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008544 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008545 int ret;
8546 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008547 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008548 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008549 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008550
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008551 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008552 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008553
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308554 if (!parms)
8555 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308556
Derek Chen6f293672019-04-01 01:40:24 -07008557 /* notify adev and input/output streams on the snd card status */
8558 adev_snd_mon_cb((void *)adev, parms);
8559
8560 list_for_each(node, &adev->active_outputs_list) {
8561 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8562 streams_output_ctxt_t,
8563 list);
8564 out_snd_mon_cb((void *)out_ctxt->output, parms);
8565 }
8566
8567 list_for_each(node, &adev->active_inputs_list) {
8568 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8569 streams_input_ctxt_t,
8570 list);
8571 in_snd_mon_cb((void *)in_ctxt->input, parms);
8572 }
8573
Zhou Songd6d71752019-05-21 18:08:51 +08008574 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308575 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8576 if (ret >= 0) {
8577 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008578 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308579 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008580 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308581 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008582 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008583 }
8584 }
8585
8586 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8587 if (ret>=0) {
8588 if (!strncmp(value, "false", 5) &&
8589 audio_extn_a2dp_source_is_suspended()) {
8590 struct audio_usecase *usecase;
8591 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008592 list_for_each(node, &adev->usecase_list) {
8593 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008594 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008595 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008596 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008597 reassign_device_list(&usecase->stream.in->device_list,
8598 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008599 select_devices(adev, usecase->id);
8600 }
Zhou Songd6d71752019-05-21 18:08:51 +08008601 }
8602 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308603 }
8604
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008605 status = voice_set_parameters(adev, parms);
8606 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008607 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008608
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008609 status = platform_set_parameters(adev->platform, parms);
8610 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008611 goto done;
8612
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008613 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8614 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008615 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008616 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8617 adev->bluetooth_nrec = true;
8618 else
8619 adev->bluetooth_nrec = false;
8620 }
8621
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008622 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8623 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008624 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8625 adev->screen_off = false;
8626 else
8627 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008628 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008629 }
8630
Eric Laurent4b084132018-10-19 17:33:43 -07008631 ret = str_parms_get_int(parms, "rotation", &val);
8632 if (ret >= 0) {
8633 bool reverse_speakers = false;
8634 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8635 switch (val) {
8636 // FIXME: note that the code below assumes that the speakers are in the correct placement
8637 // relative to the user when the device is rotated 90deg from its default rotation. This
8638 // assumption is device-specific, not platform-specific like this code.
8639 case 270:
8640 reverse_speakers = true;
8641 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8642 break;
8643 case 0:
8644 case 180:
8645 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8646 break;
8647 case 90:
8648 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8649 break;
8650 default:
8651 ALOGE("%s: unexpected rotation of %d", __func__, val);
8652 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008653 }
Eric Laurent4b084132018-10-19 17:33:43 -07008654 if (status == 0) {
8655 // check and set swap
8656 // - check if orientation changed and speaker active
8657 // - set rotation and cache the rotation value
8658 adev->camera_orientation =
8659 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8660 if (!audio_extn_is_maxx_audio_enabled())
8661 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8662 }
8663 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008664
Mingming Yin514a8bc2014-07-29 15:22:21 -07008665 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8666 if (ret >= 0) {
8667 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8668 adev->bt_wb_speech_enabled = true;
8669 else
8670 adev->bt_wb_speech_enabled = false;
8671 }
8672
Zhou Song12c29502019-03-16 10:37:18 +08008673 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8674 if (ret >= 0) {
8675 val = atoi(value);
8676 adev->swb_speech_mode = val;
8677 }
8678
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008679 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8680 if (ret >= 0) {
8681 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308682 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008683 if (audio_is_output_device(val) &&
8684 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008685 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008686 platform_get_controller_stream_from_params(parms, &controller, &stream);
8687 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8688 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008689 if (ret < 0) {
8690 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308691 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008692 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008693 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308694 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008695 /*
8696 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8697 * Per AudioPolicyManager, USB device is higher priority than WFD.
8698 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8699 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8700 * starting voice call on USB
8701 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008702 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308703 if (ret >= 0)
8704 audio_extn_usb_add_device(device, atoi(value));
8705
Zhou Song6f862822017-11-06 17:27:57 +08008706 if (!audio_extn_usb_is_tunnel_supported()) {
8707 ALOGV("detected USB connect .. disable proxy");
8708 adev->allow_afe_proxy_usage = false;
8709 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008710 }
8711 }
8712
8713 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8714 if (ret >= 0) {
8715 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308716 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008717 /*
8718 * The HDMI / Displayport disconnect handling has been moved to
8719 * audio extension to ensure that its parameters are not
8720 * invalidated prior to updating sysfs of the disconnect event
8721 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8722 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308723 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008724 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308725 if (ret >= 0)
8726 audio_extn_usb_remove_device(device, atoi(value));
8727
Zhou Song6f862822017-11-06 17:27:57 +08008728 if (!audio_extn_usb_is_tunnel_supported()) {
8729 ALOGV("detected USB disconnect .. enable proxy");
8730 adev->allow_afe_proxy_usage = true;
8731 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008732 }
8733 }
8734
Aalique Grahame22e49102018-12-18 14:23:57 -08008735 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008736 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008737
8738 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008739 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308740 struct audio_usecase *usecase;
8741 struct listnode *node;
8742 list_for_each(node, &adev->usecase_list) {
8743 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308744 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008745 is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308746 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008747 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308748 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008749 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308750 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308751 ALOGD("Switching to speaker and muting the stream before select_devices");
8752 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308753 //force device switch to re configure encoder
8754 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308755 ALOGD("Unmuting the stream after select_devices");
8756 usecase->stream.out->a2dp_compress_mute = false;
8757 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 +05308758 audio_extn_a2dp_set_handoff_mode(false);
8759 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308760 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308761 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8762 usecase->stream.out->a2dp_compress_mute) {
8763 pthread_mutex_unlock(&adev->lock);
8764 lock_output_stream(usecase->stream.out);
8765 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008766 reassign_device_list(&usecase->stream.out->device_list,
8767 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308768 check_a2dp_restore_l(adev, usecase->stream.out, true);
8769 pthread_mutex_unlock(&usecase->stream.out->lock);
8770 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308771 }
8772 }
8773 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008774
8775 //handle vr audio setparam
8776 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8777 value, sizeof(value));
8778 if (ret >= 0) {
8779 ALOGI("Setting vr mode to be %s", value);
8780 if (!strncmp(value, "true", 4)) {
8781 adev->vr_audio_mode_enabled = true;
8782 ALOGI("Setting vr mode to true");
8783 } else if (!strncmp(value, "false", 5)) {
8784 adev->vr_audio_mode_enabled = false;
8785 ALOGI("Setting vr mode to false");
8786 } else {
8787 ALOGI("wrong vr mode set");
8788 }
8789 }
8790
Eric Laurent4b084132018-10-19 17:33:43 -07008791 //FIXME: to be replaced by proper video capture properties API
8792 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8793 if (ret >= 0) {
8794 int camera_facing = CAMERA_FACING_BACK;
8795 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8796 camera_facing = CAMERA_FACING_FRONT;
8797 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8798 camera_facing = CAMERA_FACING_BACK;
8799 else {
8800 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8801 goto done;
8802 }
8803 adev->camera_orientation =
8804 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8805 struct audio_usecase *usecase;
8806 struct listnode *node;
8807 list_for_each(node, &adev->usecase_list) {
8808 usecase = node_to_item(node, struct audio_usecase, list);
8809 struct stream_in *in = usecase->stream.in;
8810 if (usecase->type == PCM_CAPTURE && in != NULL &&
8811 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8812 select_devices(adev, in->usecase);
8813 }
8814 }
8815 }
8816
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308817 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008818done:
8819 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008820 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308821error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008822 ALOGV("%s: exit with code(%d)", __func__, status);
8823 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008824}
8825
8826static char* adev_get_parameters(const struct audio_hw_device *dev,
8827 const char *keys)
8828{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308829 ALOGD("%s:%s", __func__, keys);
8830
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008831 struct audio_device *adev = (struct audio_device *)dev;
8832 struct str_parms *reply = str_parms_create();
8833 struct str_parms *query = str_parms_create_str(keys);
8834 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308835 char value[256] = {0};
8836 int ret = 0;
8837
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008838 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008839 if (reply) {
8840 str_parms_destroy(reply);
8841 }
8842 if (query) {
8843 str_parms_destroy(query);
8844 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008845 ALOGE("adev_get_parameters: failed to create query or reply");
8846 return NULL;
8847 }
8848
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008849 //handle vr audio getparam
8850
8851 ret = str_parms_get_str(query,
8852 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8853 value, sizeof(value));
8854
8855 if (ret >= 0) {
8856 bool vr_audio_enabled = false;
8857 pthread_mutex_lock(&adev->lock);
8858 vr_audio_enabled = adev->vr_audio_mode_enabled;
8859 pthread_mutex_unlock(&adev->lock);
8860
8861 ALOGI("getting vr mode to %d", vr_audio_enabled);
8862
8863 if (vr_audio_enabled) {
8864 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8865 "true");
8866 goto exit;
8867 } else {
8868 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8869 "false");
8870 goto exit;
8871 }
8872 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008873
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008874 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008875 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008876 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008877 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008878 platform_get_parameters(adev->platform, query, reply);
justinwengd5395152019-11-04 12:23:09 +08008879 audio_extn_ma_get_parameters(adev, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308880 pthread_mutex_unlock(&adev->lock);
8881
Naresh Tannirud7205b62014-06-20 02:54:48 +05308882exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008883 str = str_parms_to_str(reply);
8884 str_parms_destroy(query);
8885 str_parms_destroy(reply);
8886
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308887 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008888 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008889}
8890
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008891static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008892{
8893 return 0;
8894}
8895
8896static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8897{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008898 int ret;
8899 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008900
8901 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8902
Haynes Mathew George5191a852013-09-11 14:19:36 -07008903 pthread_mutex_lock(&adev->lock);
8904 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008905 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008906 pthread_mutex_unlock(&adev->lock);
8907 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008908}
8909
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008910static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8911 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008912{
8913 return -ENOSYS;
8914}
8915
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008916static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8917 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008918{
8919 return -ENOSYS;
8920}
8921
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008922static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8923 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008924{
8925 return -ENOSYS;
8926}
8927
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008928static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8929 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008930{
8931 return -ENOSYS;
8932}
8933
8934static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8935{
8936 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008937 struct listnode *node;
8938 struct audio_usecase *usecase = NULL;
8939 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008941 pthread_mutex_lock(&adev->lock);
8942 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05308943 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
8944 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008945 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05308946 if( mode == AUDIO_MODE_CALL_SCREEN ){
8947 adev->current_call_output = adev->primary_output;
8948 voice_start_call(adev);
8949 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008950 (mode == AUDIO_MODE_NORMAL ||
8951 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008952 list_for_each(node, &adev->usecase_list) {
8953 usecase = node_to_item(node, struct audio_usecase, list);
8954 if (usecase->type == VOICE_CALL)
8955 break;
8956 }
8957 if (usecase &&
8958 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8959 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8960 true);
8961 if (ret != 0) {
8962 /* default service interval was successfully updated,
8963 reopen USB backend with new service interval */
8964 check_usecases_codec_backend(adev,
8965 usecase,
8966 usecase->out_snd_device);
8967 }
8968 }
8969
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008970 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008971 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008972 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008973 // restore device for other active usecases after stop call
8974 list_for_each(node, &adev->usecase_list) {
8975 usecase = node_to_item(node, struct audio_usecase, list);
8976 select_devices(adev, usecase->id);
8977 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008978 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008979 }
8980 pthread_mutex_unlock(&adev->lock);
8981 return 0;
8982}
8983
8984static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8985{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008986 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008987 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008988
8989 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008990 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008991 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008992
Derek Chend2530072014-11-24 12:39:14 -08008993 if (adev->ext_hw_plugin)
8994 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008995
8996 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008997 pthread_mutex_unlock(&adev->lock);
8998
8999 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009000}
9001
9002static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
9003{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009004 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009005 return 0;
9006}
9007
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009008static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009009 const struct audio_config *config)
9010{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009011 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009012
Aalique Grahame22e49102018-12-18 14:23:57 -08009013 /* Don't know if USB HIFI in this context so use true to be conservative */
9014 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9015 true /*is_usb_hifi */) != 0)
9016 return 0;
9017
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009018 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
9019 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009020}
9021
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009022static bool adev_input_allow_hifi_record(struct audio_device *adev,
9023 audio_devices_t devices,
9024 audio_input_flags_t flags,
9025 audio_source_t source) {
9026 const bool allowed = true;
9027
9028 if (!audio_is_usb_in_device(devices))
9029 return !allowed;
9030
9031 switch (flags) {
9032 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009033 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07009034 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
9035 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009036 default:
9037 return !allowed;
9038 }
9039
9040 switch (source) {
9041 case AUDIO_SOURCE_DEFAULT:
9042 case AUDIO_SOURCE_MIC:
9043 case AUDIO_SOURCE_UNPROCESSED:
9044 break;
9045 default:
9046 return !allowed;
9047 }
9048
9049 switch (adev->mode) {
9050 case 0:
9051 break;
9052 default:
9053 return !allowed;
9054 }
9055
9056 return allowed;
9057}
9058
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009059static int adev_update_voice_comm_input_stream(struct stream_in *in,
9060 struct audio_config *config)
9061{
9062 bool valid_rate = (config->sample_rate == 8000 ||
9063 config->sample_rate == 16000 ||
9064 config->sample_rate == 32000 ||
9065 config->sample_rate == 48000);
9066 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
9067
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009068 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08009069 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009070 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9071 in->config = default_pcm_config_voip_copp;
9072 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
9073 DEFAULT_VOIP_BUF_DURATION_MS,
9074 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009075 } else {
9076 ALOGW("%s No valid input in voip, use defaults"
9077 "sample rate %u, channel mask 0x%X",
9078 __func__, config->sample_rate, in->channel_mask);
9079 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009080 in->config.rate = config->sample_rate;
9081 in->sample_rate = config->sample_rate;
9082 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009083 //XXX needed for voice_extn_compress_voip_open_input_stream
9084 in->config.rate = config->sample_rate;
9085 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05309086 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009087 voice_extn_compress_voip_is_active(in->dev)) &&
9088 (voice_extn_compress_voip_is_format_supported(in->format)) &&
9089 valid_rate && valid_ch) {
9090 voice_extn_compress_voip_open_input_stream(in);
9091 // update rate entries to match config from AF
9092 in->config.rate = config->sample_rate;
9093 in->sample_rate = config->sample_rate;
9094 } else {
9095 ALOGW("%s compress voip not active, use defaults", __func__);
9096 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009097 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009098 return 0;
9099}
9100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009101static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07009102 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009103 audio_devices_t devices,
9104 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009105 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309106 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009107 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009108 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009109{
9110 struct audio_device *adev = (struct audio_device *)dev;
9111 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009112 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009113 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009114 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309115 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009116 bool is_usb_dev = audio_is_usb_in_device(devices);
9117 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9118 devices,
9119 flags,
9120 source);
Andy Hung94320602018-10-29 18:31:12 -07009121 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9122 " sample_rate %u, channel_mask %#x, format %#x",
9123 __func__, flags, is_usb_dev, may_use_hifi_record,
9124 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309125
kunleizdff872d2018-08-20 14:40:33 +08009126 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009127 is_usb_dev = false;
9128 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9129 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9130 __func__, devices);
9131 }
9132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009133 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009134
9135 if (!(is_usb_dev && may_use_hifi_record)) {
9136 if (config->sample_rate == 0)
9137 config->sample_rate = 48000;
9138 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9139 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9140 if (config->format == AUDIO_FORMAT_DEFAULT)
9141 config->format = AUDIO_FORMAT_PCM_16_BIT;
9142
9143 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9144
Aalique Grahame22e49102018-12-18 14:23:57 -08009145 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9146 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009147 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309148 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009149
Rahul Sharma99770982019-03-06 17:05:26 +05309150 pthread_mutex_lock(&adev->lock);
9151 if (in_get_stream(adev, handle) != NULL) {
9152 ALOGW("%s, input stream already opened", __func__);
9153 ret = -EEXIST;
9154 }
9155 pthread_mutex_unlock(&adev->lock);
9156 if (ret)
9157 return ret;
9158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009159 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009160
9161 if (!in) {
9162 ALOGE("failed to allocate input stream");
9163 return -ENOMEM;
9164 }
9165
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309166 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309167 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9168 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009169 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009170 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009172 in->stream.common.get_sample_rate = in_get_sample_rate;
9173 in->stream.common.set_sample_rate = in_set_sample_rate;
9174 in->stream.common.get_buffer_size = in_get_buffer_size;
9175 in->stream.common.get_channels = in_get_channels;
9176 in->stream.common.get_format = in_get_format;
9177 in->stream.common.set_format = in_set_format;
9178 in->stream.common.standby = in_standby;
9179 in->stream.common.dump = in_dump;
9180 in->stream.common.set_parameters = in_set_parameters;
9181 in->stream.common.get_parameters = in_get_parameters;
9182 in->stream.common.add_audio_effect = in_add_audio_effect;
9183 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9184 in->stream.set_gain = in_set_gain;
9185 in->stream.read = in_read;
9186 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009187 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309188 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009189 in->stream.set_microphone_direction = in_set_microphone_direction;
9190 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009191 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009192
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009193 list_init(&in->device_list);
9194 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009195 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009196 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009197 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009198 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009199 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009200 in->bit_width = 16;
9201 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009202 in->direction = MIC_DIRECTION_UNSPECIFIED;
9203 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009204 list_init(&in->aec_list);
9205 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009206 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009207
Andy Hung94320602018-10-29 18:31:12 -07009208 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009209 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9210 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9211 /* Force channel config requested to mono if incall
9212 record is being requested for only uplink/downlink */
9213 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9214 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9215 ret = -EINVAL;
9216 goto err_open;
9217 }
9218 }
9219
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009220 if (is_usb_dev && may_use_hifi_record) {
9221 /* HiFi record selects an appropriate format, channel, rate combo
9222 depending on sink capabilities*/
9223 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9224 &config->format,
9225 &in->supported_formats[0],
9226 MAX_SUPPORTED_FORMATS,
9227 &config->channel_mask,
9228 &in->supported_channel_masks[0],
9229 MAX_SUPPORTED_CHANNEL_MASKS,
9230 &config->sample_rate,
9231 &in->supported_sample_rates[0],
9232 MAX_SUPPORTED_SAMPLE_RATES);
9233 if (ret != 0) {
9234 ret = -EINVAL;
9235 goto err_open;
9236 }
9237 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009238 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309239 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309240 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9241 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9242 in->config.format = PCM_FORMAT_S32_LE;
9243 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309244 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9245 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9246 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9247 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9248 bool ret_error = false;
9249 in->bit_width = 24;
9250 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9251 from HAL is 24_packed and 8_24
9252 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9253 24_packed return error indicating supported format is 24_packed
9254 *> In case of any other source requesting 24 bit or float return error
9255 indicating format supported is 16 bit only.
9256
9257 on error flinger will retry with supported format passed
9258 */
9259 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9260 (source != AUDIO_SOURCE_CAMCORDER)) {
9261 config->format = AUDIO_FORMAT_PCM_16_BIT;
9262 if (config->sample_rate > 48000)
9263 config->sample_rate = 48000;
9264 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009265 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9266 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309267 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9268 ret_error = true;
9269 }
9270
9271 if (ret_error) {
9272 ret = -EINVAL;
9273 goto err_open;
9274 }
9275 }
9276
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009277 in->channel_mask = config->channel_mask;
9278 in->format = config->format;
9279
9280 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309281
9282 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9283 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9284 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9285 else {
9286 ret = -EINVAL;
9287 goto err_open;
9288 }
9289 }
9290
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009291 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309292 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9293 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009294 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9295 is_low_latency = true;
9296#if LOW_LATENCY_CAPTURE_USE_CASE
9297 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9298#endif
9299 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009300 if (!in->realtime) {
9301 in->config = pcm_config_audio_capture;
9302 frame_size = audio_stream_in_frame_size(&in->stream);
9303 buffer_size = get_input_buffer_size(config->sample_rate,
9304 config->format,
9305 channel_count,
9306 is_low_latency);
9307 in->config.period_size = buffer_size / frame_size;
9308 in->config.rate = config->sample_rate;
9309 in->af_period_multiplier = 1;
9310 } else {
9311 // period size is left untouched for rt mode playback
9312 in->config = pcm_config_audio_capture_rt;
9313 in->af_period_multiplier = af_period_multiplier;
9314 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009315 }
9316
9317 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9318 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9319 in->realtime = 0;
9320 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9321 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009322 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009323 in->stream.start = in_start;
9324 in->stream.stop = in_stop;
9325 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9326 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009327 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009328 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009329 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9330 in->config = pcm_config_audio_capture;
9331 frame_size = audio_stream_in_frame_size(&in->stream);
9332 buffer_size = get_input_buffer_size(config->sample_rate,
9333 config->format,
9334 channel_count,
9335 false /*is_low_latency*/);
9336 in->config.period_size = buffer_size / frame_size;
9337 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009338 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009339 switch (config->format) {
9340 case AUDIO_FORMAT_PCM_32_BIT:
9341 in->bit_width = 32;
9342 break;
9343 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9344 case AUDIO_FORMAT_PCM_8_24_BIT:
9345 in->bit_width = 24;
9346 break;
9347 default:
9348 in->bit_width = 16;
9349 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009350 } else if (is_single_device_type_equal(&in->device_list,
9351 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9352 is_single_device_type_equal(&in->device_list,
9353 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009354 if (config->sample_rate == 0)
9355 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9356 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9357 config->sample_rate != 8000) {
9358 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9359 ret = -EINVAL;
9360 goto err_open;
9361 }
9362 if (config->format == AUDIO_FORMAT_DEFAULT)
9363 config->format = AUDIO_FORMAT_PCM_16_BIT;
9364 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9365 config->format = AUDIO_FORMAT_PCM_16_BIT;
9366 ret = -EINVAL;
9367 goto err_open;
9368 }
9369
9370 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
9371 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009372 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009373 in->af_period_multiplier = 1;
9374 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9375 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9376 (config->sample_rate == 8000 ||
9377 config->sample_rate == 16000 ||
9378 config->sample_rate == 32000 ||
9379 config->sample_rate == 48000) &&
9380 channel_count == 1) {
9381 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9382 in->config = pcm_config_audio_capture;
9383 frame_size = audio_stream_in_frame_size(&in->stream);
9384 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9385 config->sample_rate,
9386 config->format,
9387 channel_count, false /*is_low_latency*/);
9388 in->config.period_size = buffer_size / frame_size;
9389 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9390 in->config.rate = config->sample_rate;
9391 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009392 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309393 int ret_val;
9394 pthread_mutex_lock(&adev->lock);
9395 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9396 in, config, &channel_mask_updated);
9397 pthread_mutex_unlock(&adev->lock);
9398
9399 if (!ret_val) {
9400 if (channel_mask_updated == true) {
9401 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9402 __func__, config->channel_mask);
9403 ret = -EINVAL;
9404 goto err_open;
9405 }
9406 ALOGD("%s: created multi-channel session succesfully",__func__);
9407 } else if (audio_extn_compr_cap_enabled() &&
9408 audio_extn_compr_cap_format_supported(config->format) &&
9409 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9410 audio_extn_compr_cap_init(in);
9411 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309412 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309413 if (ret)
9414 goto err_open;
9415 } else {
9416 in->config = pcm_config_audio_capture;
9417 in->config.rate = config->sample_rate;
9418 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309419 in->format = config->format;
9420 frame_size = audio_stream_in_frame_size(&in->stream);
9421 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009422 config->format,
9423 channel_count,
9424 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009425 /* prevent division-by-zero */
9426 if (frame_size == 0) {
9427 ALOGE("%s: Error frame_size==0", __func__);
9428 ret = -EINVAL;
9429 goto err_open;
9430 }
9431
Revathi Uddarajud2634032017-12-07 14:42:34 +05309432 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009433 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009434
Revathi Uddarajud2634032017-12-07 14:42:34 +05309435 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9436 /* optionally use VOIP usecase depending on config(s) */
9437 ret = adev_update_voice_comm_input_stream(in, config);
9438 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009439
Revathi Uddarajud2634032017-12-07 14:42:34 +05309440 if (ret) {
9441 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9442 goto err_open;
9443 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009444 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309445
9446 /* assign concurrent capture usecase if record has to caried out from
9447 * actual hardware input source */
9448 if (audio_extn_is_concurrent_capture_enabled() &&
9449 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309450 /* Acquire lock to avoid two concurrent use cases initialized to
9451 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009452
Samyak Jainc37062f2019-04-25 18:41:06 +05309453 if (in->usecase == USECASE_AUDIO_RECORD) {
9454 pthread_mutex_lock(&adev->lock);
9455 if (!(adev->pcm_record_uc_state)) {
9456 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9457 adev->pcm_record_uc_state = 1;
9458 pthread_mutex_unlock(&adev->lock);
9459 } else {
9460 pthread_mutex_unlock(&adev->lock);
9461 /* Assign compress record use case for second record */
9462 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9463 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9464 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9465 if (audio_extn_cin_applicable_stream(in)) {
9466 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309467 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309468 if (ret)
9469 goto err_open;
9470 }
9471 }
9472 }
kunleiz28c73e72019-03-27 17:24:04 +08009473 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009474 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309475 if (audio_extn_ssr_get_stream() != in)
9476 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009477
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009478 in->sample_rate = in->config.rate;
9479
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309480 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9481 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009482 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009483 in->sample_rate, in->bit_width,
9484 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309485 register_format(in->format, in->supported_formats);
9486 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9487 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309488
Aalique Grahame22e49102018-12-18 14:23:57 -08009489 in->error_log = error_log_create(
9490 ERROR_LOG_ENTRIES,
9491 1000000000 /* aggregate consecutive identical errors within one second */);
9492
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009493 /* This stream could be for sound trigger lab,
9494 get sound trigger pcm if present */
9495 audio_extn_sound_trigger_check_and_get_session(in);
9496
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309497 lock_input_stream(in);
9498 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9499 pthread_mutex_lock(&adev->lock);
9500 in->card_status = adev->card_status;
9501 pthread_mutex_unlock(&adev->lock);
9502 pthread_mutex_unlock(&in->lock);
9503
Aalique Grahame22e49102018-12-18 14:23:57 -08009504 stream_app_type_cfg_init(&in->app_type_cfg);
9505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009506 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009507
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009508 ret = io_streams_map_insert(adev, &in->stream.common,
9509 handle, AUDIO_PATCH_HANDLE_NONE);
9510 if (ret != 0)
9511 goto err_open;
9512
Derek Chenf939fb72018-11-13 13:34:41 -08009513 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9514 calloc(1, sizeof(streams_input_ctxt_t));
9515 if (in_ctxt == NULL) {
9516 ALOGE("%s fail to allocate input ctxt", __func__);
9517 ret = -ENOMEM;
9518 goto err_open;
9519 }
9520 in_ctxt->input = in;
9521
9522 pthread_mutex_lock(&adev->lock);
9523 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9524 pthread_mutex_unlock(&adev->lock);
9525
Eric Laurent994a6932013-07-17 11:51:42 -07009526 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009527 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009528
9529err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309530 if (in->usecase == USECASE_AUDIO_RECORD) {
9531 pthread_mutex_lock(&adev->lock);
9532 adev->pcm_record_uc_state = 0;
9533 pthread_mutex_unlock(&adev->lock);
9534 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009535 free(in);
9536 *stream_in = NULL;
9537 return ret;
9538}
9539
9540static void adev_close_input_stream(struct audio_hw_device *dev,
9541 struct audio_stream_in *stream)
9542{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009543 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009544 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009545 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309546
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309547 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009548
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009549 if (in == NULL) {
9550 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9551 return;
9552 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009553 io_streams_map_remove(adev, in->capture_handle);
9554
kunleiz70e57612018-12-28 17:50:23 +08009555 /* must deregister from sndmonitor first to prevent races
9556 * between the callback and close_stream
9557 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309558 audio_extn_snd_mon_unregister_listener(stream);
9559
kunleiz70e57612018-12-28 17:50:23 +08009560 /* Disable echo reference if there are no active input, hfp call
9561 * and sound trigger while closing input stream
9562 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009563 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009564 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009565 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9566 struct listnode out_devices;
9567 list_init(&out_devices);
9568 platform_set_echo_reference(adev, false, &out_devices);
9569 } else
kunleiz70e57612018-12-28 17:50:23 +08009570 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309571
Weiyin Jiang2995f662019-04-17 14:25:12 +08009572 error_log_destroy(in->error_log);
9573 in->error_log = NULL;
9574
Pallavid7c7a272018-01-16 11:22:55 +05309575
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009576 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309577 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009578 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309579 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009580 if (ret != 0)
9581 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9582 __func__, ret);
9583 } else
9584 in_standby(&stream->common);
9585
Revathi Uddarajud2634032017-12-07 14:42:34 +05309586 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309587 if (in->usecase == USECASE_AUDIO_RECORD) {
9588 adev->pcm_record_uc_state = 0;
9589 }
9590
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009591 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9592 adev->enable_voicerx = false;
9593 }
9594
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009595 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009596 audio_extn_ssr_deinit();
9597 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009598
Garmond Leunge2433c32017-09-28 21:51:22 -07009599 if (audio_extn_ffv_get_stream() == in) {
9600 audio_extn_ffv_stream_deinit();
9601 }
9602
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309603 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009604 audio_extn_compr_cap_format_supported(in->config.format))
9605 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309606
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309607 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309608 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009609
Mingming Yinfd7607b2016-01-22 12:48:44 -08009610 if (in->is_st_session) {
9611 ALOGV("%s: sound trigger pcm stop lab", __func__);
9612 audio_extn_sound_trigger_stop_lab(in);
9613 }
Derek Chenf939fb72018-11-13 13:34:41 -08009614 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9615 if (in_ctxt != NULL) {
9616 list_remove(&in_ctxt->list);
9617 free(in_ctxt);
9618 } else {
9619 ALOGW("%s, input stream already closed", __func__);
9620 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009621 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309622 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009623 return;
9624}
9625
Aalique Grahame22e49102018-12-18 14:23:57 -08009626/* verifies input and output devices and their capabilities.
9627 *
9628 * This verification is required when enabling extended bit-depth or
9629 * sampling rates, as not all qcom products support it.
9630 *
9631 * Suitable for calling only on initialization such as adev_open().
9632 * It fills the audio_device use_case_table[] array.
9633 *
9634 * Has a side-effect that it needs to configure audio routing / devices
9635 * in order to power up the devices and read the device parameters.
9636 * It does not acquire any hw device lock. Should restore the devices
9637 * back to "normal state" upon completion.
9638 */
9639static int adev_verify_devices(struct audio_device *adev)
9640{
9641 /* enumeration is a bit difficult because one really wants to pull
9642 * the use_case, device id, etc from the hidden pcm_device_table[].
9643 * In this case there are the following use cases and device ids.
9644 *
9645 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9646 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9647 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9648 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9649 * [USECASE_AUDIO_RECORD] = {0, 0},
9650 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9651 * [USECASE_VOICE_CALL] = {2, 2},
9652 *
9653 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9654 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9655 */
9656
9657 /* should be the usecases enabled in adev_open_input_stream() */
9658 static const int test_in_usecases[] = {
9659 USECASE_AUDIO_RECORD,
9660 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9661 };
9662 /* should be the usecases enabled in adev_open_output_stream()*/
9663 static const int test_out_usecases[] = {
9664 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9665 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9666 };
9667 static const usecase_type_t usecase_type_by_dir[] = {
9668 PCM_PLAYBACK,
9669 PCM_CAPTURE,
9670 };
9671 static const unsigned flags_by_dir[] = {
9672 PCM_OUT,
9673 PCM_IN,
9674 };
9675
9676 size_t i;
9677 unsigned dir;
9678 const unsigned card_id = adev->snd_card;
9679
9680 for (dir = 0; dir < 2; ++dir) {
9681 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9682 const unsigned flags_dir = flags_by_dir[dir];
9683 const size_t testsize =
9684 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9685 const int *testcases =
9686 dir ? test_in_usecases : test_out_usecases;
9687 const audio_devices_t audio_device =
9688 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9689
9690 for (i = 0; i < testsize; ++i) {
9691 const audio_usecase_t audio_usecase = testcases[i];
9692 int device_id;
9693 struct pcm_params **pparams;
9694 struct stream_out out;
9695 struct stream_in in;
9696 struct audio_usecase uc_info;
9697 int retval;
9698
9699 pparams = &adev->use_case_table[audio_usecase];
9700 pcm_params_free(*pparams); /* can accept null input */
9701 *pparams = NULL;
9702
9703 /* find the device ID for the use case (signed, for error) */
9704 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9705 if (device_id < 0)
9706 continue;
9707
9708 /* prepare structures for device probing */
9709 memset(&uc_info, 0, sizeof(uc_info));
9710 uc_info.id = audio_usecase;
9711 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009712 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009713 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009714 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009715 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009716 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009717 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9718 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009719 }
9720 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009721 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009722 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009723 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009724 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009725 uc_info.in_snd_device = SND_DEVICE_NONE;
9726 uc_info.out_snd_device = SND_DEVICE_NONE;
9727 list_add_tail(&adev->usecase_list, &uc_info.list);
9728
9729 /* select device - similar to start_(in/out)put_stream() */
9730 retval = select_devices(adev, audio_usecase);
9731 if (retval >= 0) {
9732 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9733#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009734 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009735 if (*pparams) {
9736 ALOGV("%s: (%s) card %d device %d", __func__,
9737 dir ? "input" : "output", card_id, device_id);
9738 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9739 } else {
9740 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9741 }
9742#endif
9743 }
9744
9745 /* deselect device - similar to stop_(in/out)put_stream() */
9746 /* 1. Get and set stream specific mixer controls */
9747 retval = disable_audio_route(adev, &uc_info);
9748 /* 2. Disable the rx device */
9749 retval = disable_snd_device(adev,
9750 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9751 list_remove(&uc_info.list);
9752 }
9753 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009754 return 0;
9755}
9756
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009757int update_patch(unsigned int num_sources,
9758 const struct audio_port_config *sources,
9759 unsigned int num_sinks,
9760 const struct audio_port_config *sinks,
9761 audio_patch_handle_t handle,
9762 struct audio_patch_info *p_info,
9763 patch_type_t patch_type, bool new_patch)
9764{
9765 ALOGD("%s: enter", __func__);
9766
9767 if (p_info == NULL) {
9768 ALOGE("%s: Invalid patch pointer", __func__);
9769 return -EINVAL;
9770 }
9771
9772 if (new_patch) {
9773 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9774 if (p_info->patch == NULL) {
9775 ALOGE("%s: Could not allocate patch", __func__);
9776 return -ENOMEM;
9777 }
9778 }
9779
9780 p_info->patch->id = handle;
9781 p_info->patch->num_sources = num_sources;
9782 p_info->patch->num_sinks = num_sinks;
9783
9784 for (int i = 0; i < num_sources; i++)
9785 p_info->patch->sources[i] = sources[i];
9786 for (int i = 0; i < num_sinks; i++)
9787 p_info->patch->sinks[i] = sinks[i];
9788
9789 p_info->patch_type = patch_type;
9790 return 0;
9791}
9792
9793audio_patch_handle_t generate_patch_handle()
9794{
9795 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9796 if (++patch_handle < 0)
9797 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9798 return patch_handle;
9799}
9800
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309801int adev_create_audio_patch(struct audio_hw_device *dev,
9802 unsigned int num_sources,
9803 const struct audio_port_config *sources,
9804 unsigned int num_sinks,
9805 const struct audio_port_config *sinks,
9806 audio_patch_handle_t *handle)
9807{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009808 int ret = 0;
9809 struct audio_device *adev = (struct audio_device *)dev;
9810 struct audio_patch_info *p_info = NULL;
9811 patch_type_t patch_type = PATCH_NONE;
9812 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9813 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9814 struct audio_stream_info *s_info = NULL;
9815 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009816 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009817 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9818 bool new_patch = false;
9819 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309820
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009821 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9822 num_sources, num_sinks, *handle);
9823
9824 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9825 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9826 ALOGE("%s: Invalid patch arguments", __func__);
9827 ret = -EINVAL;
9828 goto done;
9829 }
9830
9831 if (num_sources > 1) {
9832 ALOGE("%s: Multiple sources are not supported", __func__);
9833 ret = -EINVAL;
9834 goto done;
9835 }
9836
9837 if (sources == NULL || sinks == NULL) {
9838 ALOGE("%s: Invalid sources or sinks port config", __func__);
9839 ret = -EINVAL;
9840 goto done;
9841 }
9842
9843 ALOGV("%s: source role %d, source type %d", __func__,
9844 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009845 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009846
9847 // Populate source/sink information and fetch stream info
9848 switch (sources[0].type) {
9849 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9850 device_type = sources[0].ext.device.type;
9851 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009852 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009853 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9854 patch_type = PATCH_CAPTURE;
9855 io_handle = sinks[0].ext.mix.handle;
9856 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009857 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009858 __func__, device_type, io_handle);
9859 } else {
9860 // Device to device patch is not implemented.
9861 // This space will need changes if audio HAL
9862 // handles device to device patches in the future.
9863 patch_type = PATCH_DEVICE_LOOPBACK;
9864 }
9865 break;
9866 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9867 io_handle = sources[0].ext.mix.handle;
9868 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009869 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009870 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009871 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009872 }
9873 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009874 ALOGD("%s: Playback patch from mix handle %d to device %x",
9875 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009876 break;
9877 case AUDIO_PORT_TYPE_SESSION:
9878 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009879 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9880 ret = -EINVAL;
9881 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009882 }
9883
9884 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009885
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009886 // Generate patch info and update patch
9887 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009888 *handle = generate_patch_handle();
9889 p_info = (struct audio_patch_info *)
9890 calloc(1, sizeof(struct audio_patch_info));
9891 if (p_info == NULL) {
9892 ALOGE("%s: Failed to allocate memory", __func__);
9893 pthread_mutex_unlock(&adev->lock);
9894 ret = -ENOMEM;
9895 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009896 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009897 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009898 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009899 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009900 if (p_info == NULL) {
9901 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9902 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009903 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009904 ret = -EINVAL;
9905 goto done;
9906 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009907 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009908 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009909 *handle, p_info, patch_type, new_patch);
9910
9911 // Fetch stream info of associated mix for playback or capture patches
9912 if (p_info->patch_type == PATCH_PLAYBACK ||
9913 p_info->patch_type == PATCH_CAPTURE) {
9914 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9915 if (s_info == NULL) {
9916 ALOGE("%s: Failed to obtain stream info", __func__);
9917 if (new_patch)
9918 free(p_info);
9919 pthread_mutex_unlock(&adev->lock);
9920 ret = -EINVAL;
9921 goto done;
9922 }
9923 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9924 s_info->patch_handle = *handle;
9925 stream = s_info->stream;
9926 }
9927 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009928
9929 // Update routing for stream
9930 if (stream != NULL) {
9931 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009932 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009933 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009934 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009935 if (ret < 0) {
9936 pthread_mutex_lock(&adev->lock);
9937 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9938 if (new_patch)
9939 free(p_info);
9940 pthread_mutex_unlock(&adev->lock);
9941 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9942 goto done;
9943 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009944 }
9945
9946 // Add new patch to patch map
9947 if (!ret && new_patch) {
9948 pthread_mutex_lock(&adev->lock);
9949 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009950 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009951 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009952 }
9953
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009954done:
9955 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009956 num_sources,
9957 sources,
9958 num_sinks,
9959 sinks,
9960 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009961 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009962 num_sources,
9963 sources,
9964 num_sinks,
9965 sinks,
9966 handle);
9967 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309968}
9969
9970int adev_release_audio_patch(struct audio_hw_device *dev,
9971 audio_patch_handle_t handle)
9972{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009973 struct audio_device *adev = (struct audio_device *) dev;
9974 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009975 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009976 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -08009977
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009978 if (handle == AUDIO_PATCH_HANDLE_NONE) {
9979 ALOGE("%s: Invalid patch handle %d", __func__, handle);
9980 ret = -EINVAL;
9981 goto done;
9982 }
9983
9984 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009985 pthread_mutex_lock(&adev->lock);
9986 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009987 if (p_info == NULL) {
9988 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009989 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009990 ret = -EINVAL;
9991 goto done;
9992 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009993 struct audio_patch *patch = p_info->patch;
9994 if (patch == NULL) {
9995 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009996 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009997 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009998 goto done;
9999 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010000 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
10001 switch (patch->sources[0].type) {
10002 case AUDIO_PORT_TYPE_MIX:
10003 io_handle = patch->sources[0].ext.mix.handle;
10004 break;
10005 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010006 if (p_info->patch_type == PATCH_CAPTURE)
10007 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010008 break;
10009 case AUDIO_PORT_TYPE_SESSION:
10010 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010011 pthread_mutex_unlock(&adev->lock);
10012 ret = -EINVAL;
10013 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010014 }
10015
10016 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010017 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010018 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010019 if (patch_type == PATCH_PLAYBACK ||
10020 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010021 struct audio_stream_info *s_info =
10022 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
10023 if (s_info == NULL) {
10024 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
10025 pthread_mutex_unlock(&adev->lock);
10026 goto done;
10027 }
10028 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
10029 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010030 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010031 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010032
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010033 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010034 struct listnode devices;
10035 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010036 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010037 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -070010038 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010039 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010040 }
10041
10042 if (ret < 0)
10043 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
10044
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010045done:
10046 audio_extn_hw_loopback_release_audio_patch(dev, handle);
10047 audio_extn_auto_hal_release_audio_patch(dev, handle);
10048
10049 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -080010050 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010051}
10052
10053int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
10054{
Derek Chenf13dd492018-11-13 14:53:51 -080010055 int ret = 0;
10056
10057 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
10058 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
10059 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010060}
10061
10062int adev_set_audio_port_config(struct audio_hw_device *dev,
10063 const struct audio_port_config *config)
10064{
Derek Chenf13dd492018-11-13 14:53:51 -080010065 int ret = 0;
10066
10067 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
10068 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
10069 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010070}
10071
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -070010072static int adev_dump(const audio_hw_device_t *device __unused,
10073 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010074{
10075 return 0;
10076}
10077
10078static int adev_close(hw_device_t *device)
10079{
Aalique Grahame22e49102018-12-18 14:23:57 -080010080 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010081 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -070010082
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +053010083 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -070010084 return 0;
10085
10086 pthread_mutex_lock(&adev_init_lock);
10087
10088 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +053010089 if (audio_extn_spkr_prot_is_enabled())
10090 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +053010091 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010092 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -070010093 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -080010094 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010095 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -080010096 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010097 audio_extn_utils_release_streams_cfg_lists(
10098 &adev->streams_output_cfg_list,
10099 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010100 if (audio_extn_qap_is_enabled())
10101 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010102 if (audio_extn_qaf_is_enabled())
10103 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -070010104 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +080010105 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -070010106 free(adev->snd_dev_ref_cnt);
10107 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010108 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
10109 pcm_params_free(adev->use_case_table[i]);
10110 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010111 if (adev->adm_deinit)
10112 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010113 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010114 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010115 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010116 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010117 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010118 if (adev->device_cfg_params) {
10119 free(adev->device_cfg_params);
10120 adev->device_cfg_params = NULL;
10121 }
Derek Chend2530072014-11-24 12:39:14 -080010122 if(adev->ext_hw_plugin)
10123 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010124 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010125 free_map(adev->patch_map);
10126 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010127 free(device);
10128 adev = NULL;
10129 }
10130 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010131 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010132 return 0;
10133}
10134
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010135/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10136 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10137 * just that it _might_ work.
10138 */
10139static int period_size_is_plausible_for_low_latency(int period_size)
10140{
10141 switch (period_size) {
10142 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010143 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010144 case 240:
10145 case 320:
10146 case 480:
10147 return 1;
10148 default:
10149 return 0;
10150 }
10151}
10152
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010153static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10154{
10155 bool is_snd_card_status = false;
10156 bool is_ext_device_status = false;
10157 char value[32];
10158 int card = -1;
10159 card_status_t status;
10160
10161 if (cookie != adev || !parms)
10162 return;
10163
10164 if (!parse_snd_card_status(parms, &card, &status)) {
10165 is_snd_card_status = true;
10166 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10167 is_ext_device_status = true;
10168 } else {
10169 // not a valid event
10170 return;
10171 }
10172
10173 pthread_mutex_lock(&adev->lock);
10174 if (card == adev->snd_card || is_ext_device_status) {
10175 if (is_snd_card_status && adev->card_status != status) {
10176 adev->card_status = status;
10177 platform_snd_card_update(adev->platform, status);
10178 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010179 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010180 if (status == CARD_STATUS_OFFLINE)
10181 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010182 } else if (is_ext_device_status) {
10183 platform_set_parameters(adev->platform, parms);
10184 }
10185 }
10186 pthread_mutex_unlock(&adev->lock);
10187 return;
10188}
10189
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010190/* out and adev lock held */
10191static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10192{
10193 struct audio_usecase *uc_info;
10194 float left_p;
10195 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010196 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010197
10198 uc_info = get_usecase_from_list(adev, out->usecase);
10199 if (uc_info == NULL) {
10200 ALOGE("%s: Could not find the usecase (%d) in the list",
10201 __func__, out->usecase);
10202 return -EINVAL;
10203 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010204 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010205
10206 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10207 out->usecase, use_case_table[out->usecase]);
10208
10209 if (restore) {
10210 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010211 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010212 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010213 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10214 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010215 pthread_mutex_lock(&out->compr_mute_lock);
10216 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010217 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010218 out->a2dp_compress_mute = false;
10219 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10220 }
10221 pthread_mutex_unlock(&out->compr_mute_lock);
10222 }
10223 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010224 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10225 // mute compress stream if suspended
10226 pthread_mutex_lock(&out->compr_mute_lock);
10227 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010228 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010229 assign_devices(&devices, &out->device_list);
10230 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010231 left_p = out->volume_l;
10232 right_p = out->volume_r;
10233 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10234 compress_pause(out->compr);
10235 out_set_compr_volume(&out->stream, (float)0, (float)0);
10236 out->a2dp_compress_mute = true;
10237 select_devices(adev, out->usecase);
10238 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10239 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010240 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010241 out->volume_l = left_p;
10242 out->volume_r = right_p;
10243 }
Zhou Songc576a452019-09-09 14:17:40 +080010244 pthread_mutex_unlock(&out->compr_mute_lock);
10245 } else {
10246 // tear down a2dp path for non offloaded streams
10247 if (audio_extn_a2dp_source_is_suspended())
10248 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010249 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010250 }
10251 ALOGV("%s: exit", __func__);
10252 return 0;
10253}
10254
10255int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10256{
10257 int ret = 0;
10258
10259 lock_output_stream(out);
10260 pthread_mutex_lock(&adev->lock);
10261
10262 ret = check_a2dp_restore_l(adev, out, restore);
10263
10264 pthread_mutex_unlock(&adev->lock);
10265 pthread_mutex_unlock(&out->lock);
10266 return ret;
10267}
10268
Haynes Mathew George01156f92018-04-13 15:29:54 -070010269void adev_on_battery_status_changed(bool charging)
10270{
10271 pthread_mutex_lock(&adev->lock);
10272 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10273 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010274 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010275 pthread_mutex_unlock(&adev->lock);
10276}
10277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010278static int adev_open(const hw_module_t *module, const char *name,
10279 hw_device_t **device)
10280{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010281 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010282 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010283 char mixer_ctl_name[128] = {0};
10284 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010285
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010286 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010287 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10288
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010289 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010290 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010291 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010292 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010293 ALOGD("%s: returning existing instance of adev", __func__);
10294 ALOGD("%s: exit", __func__);
10295 pthread_mutex_unlock(&adev_init_lock);
10296 return 0;
10297 }
10298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010299 adev = calloc(1, sizeof(struct audio_device));
10300
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010301 if (!adev) {
10302 pthread_mutex_unlock(&adev_init_lock);
10303 return -ENOMEM;
10304 }
10305
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010306 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10307
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010308 // register audio ext hidl at the earliest
10309 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010310#ifdef DYNAMIC_LOG_ENABLED
10311 register_for_dynamic_logging("hal");
10312#endif
10313
Derek Chenf939fb72018-11-13 13:34:41 -080010314 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010315 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010316 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10317 maj_version = atoi(value);
10318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010319 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010320 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010321 adev->device.common.module = (struct hw_module_t *)module;
10322 adev->device.common.close = adev_close;
10323
10324 adev->device.init_check = adev_init_check;
10325 adev->device.set_voice_volume = adev_set_voice_volume;
10326 adev->device.set_master_volume = adev_set_master_volume;
10327 adev->device.get_master_volume = adev_get_master_volume;
10328 adev->device.set_master_mute = adev_set_master_mute;
10329 adev->device.get_master_mute = adev_get_master_mute;
10330 adev->device.set_mode = adev_set_mode;
10331 adev->device.set_mic_mute = adev_set_mic_mute;
10332 adev->device.get_mic_mute = adev_get_mic_mute;
10333 adev->device.set_parameters = adev_set_parameters;
10334 adev->device.get_parameters = adev_get_parameters;
10335 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10336 adev->device.open_output_stream = adev_open_output_stream;
10337 adev->device.close_output_stream = adev_close_output_stream;
10338 adev->device.open_input_stream = adev_open_input_stream;
10339 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010340 adev->device.create_audio_patch = adev_create_audio_patch;
10341 adev->device.release_audio_patch = adev_release_audio_patch;
10342 adev->device.get_audio_port = adev_get_audio_port;
10343 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010344 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010345 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010346
10347 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010348 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010349 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010350 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010351 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010352 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010353 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010354 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010355 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010356 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010357 /* Init audio and voice feature */
10358 audio_extn_feature_init();
10359 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010360 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010361 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010362 list_init(&adev->active_inputs_list);
10363 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010364 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010365 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10366 audio_extn_utils_hash_eq);
10367 if (!adev->io_streams_map) {
10368 ALOGE("%s: Could not create io streams map", __func__);
10369 ret = -ENOMEM;
10370 goto adev_open_err;
10371 }
10372 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10373 audio_extn_utils_hash_eq);
10374 if (!adev->patch_map) {
10375 ALOGE("%s: Could not create audio patch map", __func__);
10376 ret = -ENOMEM;
10377 goto adev_open_err;
10378 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010379 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010380 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010381 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010382 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010383 adev->perf_lock_opts[0] = 0x101;
10384 adev->perf_lock_opts[1] = 0x20E;
10385 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010386 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010387 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010388 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010389 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010390
Zhou Song68ebc352019-12-05 17:11:15 +080010391 audio_extn_perf_lock_init();
10392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010393 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010394 adev->platform = platform_init(adev);
10395 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010396 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010397 ret = -EINVAL;
10398 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010399 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010400
Aalique Grahame22e49102018-12-18 14:23:57 -080010401 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010402 if (audio_extn_qap_is_enabled()) {
10403 ret = audio_extn_qap_init(adev);
10404 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010405 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010406 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010407 }
10408 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10409 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10410 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010411
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010412 if (audio_extn_qaf_is_enabled()) {
10413 ret = audio_extn_qaf_init(adev);
10414 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010415 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010416 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010417 }
10418
10419 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10420 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10421 }
10422
Derek Chenae7b0342019-02-08 15:17:04 -080010423 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010424 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10425
Eric Laurentc4aef752013-09-12 17:45:53 -070010426 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10427 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10428 if (adev->visualizer_lib == NULL) {
10429 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10430 } else {
10431 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10432 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010433 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010434 "visualizer_hal_start_output");
10435 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010436 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010437 "visualizer_hal_stop_output");
10438 }
10439 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010440 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010441 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010442 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010443 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010444 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010445 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010446
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010447 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10448 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10449 if (adev->offload_effects_lib == NULL) {
10450 ALOGE("%s: DLOPEN failed for %s", __func__,
10451 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10452 } else {
10453 ALOGV("%s: DLOPEN successful for %s", __func__,
10454 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10455 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010456 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010457 "offload_effects_bundle_hal_start_output");
10458 adev->offload_effects_stop_output =
10459 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10460 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010461 adev->offload_effects_set_hpx_state =
10462 (int (*)(bool))dlsym(adev->offload_effects_lib,
10463 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010464 adev->offload_effects_get_parameters =
10465 (void (*)(struct str_parms *, struct str_parms *))
10466 dlsym(adev->offload_effects_lib,
10467 "offload_effects_bundle_get_parameters");
10468 adev->offload_effects_set_parameters =
10469 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10470 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010471 }
10472 }
10473
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010474 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10475 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10476 if (adev->adm_lib == NULL) {
10477 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10478 } else {
10479 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10480 adev->adm_init = (adm_init_t)
10481 dlsym(adev->adm_lib, "adm_init");
10482 adev->adm_deinit = (adm_deinit_t)
10483 dlsym(adev->adm_lib, "adm_deinit");
10484 adev->adm_register_input_stream = (adm_register_input_stream_t)
10485 dlsym(adev->adm_lib, "adm_register_input_stream");
10486 adev->adm_register_output_stream = (adm_register_output_stream_t)
10487 dlsym(adev->adm_lib, "adm_register_output_stream");
10488 adev->adm_deregister_stream = (adm_deregister_stream_t)
10489 dlsym(adev->adm_lib, "adm_deregister_stream");
10490 adev->adm_request_focus = (adm_request_focus_t)
10491 dlsym(adev->adm_lib, "adm_request_focus");
10492 adev->adm_abandon_focus = (adm_abandon_focus_t)
10493 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010494 adev->adm_set_config = (adm_set_config_t)
10495 dlsym(adev->adm_lib, "adm_set_config");
10496 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10497 dlsym(adev->adm_lib, "adm_request_focus_v2");
10498 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10499 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10500 adev->adm_on_routing_change = (adm_on_routing_change_t)
10501 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010502 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10503 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010504 }
10505 }
10506
Aalique Grahame22e49102018-12-18 14:23:57 -080010507 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010508 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010509 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010510 //initialize this to false for now,
10511 //this will be set to true through set param
10512 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010513
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010514 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010515 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010516
10517 if (k_enable_extended_precision)
10518 adev_verify_devices(adev);
10519
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010520 adev->dsp_bit_width_enforce_mode =
10521 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010522
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010523 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10524 &adev->streams_output_cfg_list,
10525 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010526
Kiran Kandi910e1862013-10-29 13:29:42 -070010527 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010528
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010529 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010530 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010531 trial = atoi(value);
10532 if (period_size_is_plausible_for_low_latency(trial)) {
10533 pcm_config_low_latency.period_size = trial;
10534 pcm_config_low_latency.start_threshold = trial / 4;
10535 pcm_config_low_latency.avail_min = trial / 4;
10536 configured_low_latency_capture_period_size = trial;
10537 }
10538 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010539 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10540 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010541 trial = atoi(value);
10542 if (period_size_is_plausible_for_low_latency(trial)) {
10543 configured_low_latency_capture_period_size = trial;
10544 }
10545 }
10546
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010547 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10548
Eric Laurent4b084132018-10-19 17:33:43 -070010549 adev->camera_orientation = CAMERA_DEFAULT;
10550
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010551 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010552 af_period_multiplier = atoi(value);
10553 if (af_period_multiplier < 0)
10554 af_period_multiplier = 2;
10555 else if (af_period_multiplier > 4)
10556 af_period_multiplier = 4;
10557
10558 ALOGV("new period_multiplier = %d", af_period_multiplier);
10559 }
10560
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010561 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010562
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010563 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010564 pthread_mutex_unlock(&adev_init_lock);
10565
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010566 if (adev->adm_init)
10567 adev->adm_data = adev->adm_init();
10568
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010569 qahwi_init(*device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010570 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010571
10572 audio_extn_snd_mon_init();
10573 pthread_mutex_lock(&adev->lock);
10574 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10575 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010576 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10577 /*
10578 * if the battery state callback happens before charging can be queried,
10579 * it will be guarded with the adev->lock held in the cb function and so
10580 * the callback value will reflect the latest state
10581 */
10582 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010583 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010584 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010585 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010586 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010587 /* Allocate memory for Device config params */
10588 adev->device_cfg_params = (struct audio_device_config_param*)
10589 calloc(platform_get_max_codec_backend(),
10590 sizeof(struct audio_device_config_param));
10591 if (adev->device_cfg_params == NULL)
10592 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010593
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010594 /*
10595 * Check if new PSPD matrix mixer control is supported. If not
10596 * supported, then set flag so that old mixer ctrl is sent while
10597 * sending pspd coefficients on older kernel version. Query mixer
10598 * control for default pcm id and channel value one.
10599 */
10600 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10601 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10602
10603 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10604 if (!ctl) {
10605 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10606 __func__, mixer_ctl_name);
10607 adev->use_old_pspd_mix_ctrl = true;
10608 }
10609
Eric Laurent994a6932013-07-17 11:51:42 -070010610 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010611 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010612
10613adev_open_err:
10614 free_map(adev->patch_map);
10615 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010616 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010617 pthread_mutex_destroy(&adev->lock);
10618 free(adev);
10619 adev = NULL;
10620 *device = NULL;
10621 pthread_mutex_unlock(&adev_init_lock);
10622 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010623}
10624
10625static struct hw_module_methods_t hal_module_methods = {
10626 .open = adev_open,
10627};
10628
10629struct audio_module HAL_MODULE_INFO_SYM = {
10630 .common = {
10631 .tag = HARDWARE_MODULE_TAG,
10632 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10633 .hal_api_version = HARDWARE_HAL_API_VERSION,
10634 .id = AUDIO_HARDWARE_MODULE_ID,
10635 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010636 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010637 .methods = &hal_module_methods,
10638 },
10639};