blob: b87387429f9374f39483acf75a9f2e90d33686ae [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>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080072#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070093#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053094#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053095#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070096#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070097#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070098
Aalique Grahame22e49102018-12-18 14:23:57 -080099#define RECORD_GAIN_MIN 0.0f
100#define RECORD_GAIN_MAX 1.0f
101#define RECORD_VOLUME_CTL_MAX 0x2000
102
103/* treat as unsigned Q1.13 */
104#define APP_TYPE_GAIN_DEFAULT 0x2000
105
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700106#define PROXY_OPEN_RETRY_COUNT 100
107#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800108
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800109#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
110 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
111 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
112#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
113 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800114
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700115#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700116#define DEFAULT_VOIP_BUF_DURATION_MS 20
117#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
118#define DEFAULT_VOIP_SAMP_RATE 48000
119
120#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
121
122struct pcm_config default_pcm_config_voip_copp = {
123 .channels = 1,
124 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
125 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
126 .period_count = 2,
127 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800128 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
129 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700130};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700131
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700132#define MIN_CHANNEL_COUNT 1
133#define DEFAULT_CHANNEL_COUNT 2
134#define MAX_HIFI_CHANNEL_COUNT 8
135
Aalique Grahame22e49102018-12-18 14:23:57 -0800136#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
137#define MAX_CHANNEL_COUNT 1
138#else
139#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
140#define XSTR(x) STR(x)
141#define STR(x) #x
142#endif
143
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700144static unsigned int configured_low_latency_capture_period_size =
145 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
146
Haynes Mathew George16081042017-05-31 17:16:49 -0700147#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
148#define MMAP_PERIOD_COUNT_MIN 32
149#define MMAP_PERIOD_COUNT_MAX 512
150#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
151
Aalique Grahame22e49102018-12-18 14:23:57 -0800152/* This constant enables extended precision handling.
153 * TODO The flag is off until more testing is done.
154 */
155static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700156extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800157
Eric Laurentb23d5282013-05-14 15:27:20 -0700158struct pcm_config pcm_config_deep_buffer = {
159 .channels = 2,
160 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
161 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
162 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
163 .format = PCM_FORMAT_S16_LE,
164 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
165 .stop_threshold = INT_MAX,
166 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
167};
168
169struct pcm_config pcm_config_low_latency = {
170 .channels = 2,
171 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
172 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
173 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
174 .format = PCM_FORMAT_S16_LE,
175 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
176 .stop_threshold = INT_MAX,
177 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
178};
179
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800180struct pcm_config pcm_config_haptics_audio = {
181 .channels = 1,
182 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
183 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
184 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
185 .format = PCM_FORMAT_S16_LE,
186 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
187 .stop_threshold = INT_MAX,
188 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
189};
190
191struct pcm_config pcm_config_haptics = {
192 .channels = 1,
193 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
194 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
195 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
198 .stop_threshold = INT_MAX,
199 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
200};
201
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700202static int af_period_multiplier = 4;
203struct pcm_config pcm_config_rt = {
204 .channels = 2,
205 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
206 .period_size = ULL_PERIOD_SIZE, //1 ms
207 .period_count = 512, //=> buffer size is 512ms
208 .format = PCM_FORMAT_S16_LE,
209 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
210 .stop_threshold = INT_MAX,
211 .silence_threshold = 0,
212 .silence_size = 0,
213 .avail_min = ULL_PERIOD_SIZE, //1 ms
214};
215
Eric Laurentb23d5282013-05-14 15:27:20 -0700216struct pcm_config pcm_config_hdmi_multi = {
217 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
218 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
219 .period_size = HDMI_MULTI_PERIOD_SIZE,
220 .period_count = HDMI_MULTI_PERIOD_COUNT,
221 .format = PCM_FORMAT_S16_LE,
222 .start_threshold = 0,
223 .stop_threshold = INT_MAX,
224 .avail_min = 0,
225};
226
Haynes Mathew George16081042017-05-31 17:16:49 -0700227struct pcm_config pcm_config_mmap_playback = {
228 .channels = 2,
229 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
230 .period_size = MMAP_PERIOD_SIZE,
231 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
232 .format = PCM_FORMAT_S16_LE,
233 .start_threshold = MMAP_PERIOD_SIZE*8,
234 .stop_threshold = INT32_MAX,
235 .silence_threshold = 0,
236 .silence_size = 0,
237 .avail_min = MMAP_PERIOD_SIZE, //1 ms
238};
239
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700240struct pcm_config pcm_config_hifi = {
241 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
242 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
243 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
244 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
245 .format = PCM_FORMAT_S24_3LE,
246 .start_threshold = 0,
247 .stop_threshold = INT_MAX,
248 .avail_min = 0,
249};
250
Eric Laurentb23d5282013-05-14 15:27:20 -0700251struct pcm_config pcm_config_audio_capture = {
252 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700253 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
254 .format = PCM_FORMAT_S16_LE,
255};
256
Haynes Mathew George16081042017-05-31 17:16:49 -0700257struct pcm_config pcm_config_mmap_capture = {
258 .channels = 2,
259 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
260 .period_size = MMAP_PERIOD_SIZE,
261 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
262 .format = PCM_FORMAT_S16_LE,
263 .start_threshold = 0,
264 .stop_threshold = INT_MAX,
265 .silence_threshold = 0,
266 .silence_size = 0,
267 .avail_min = MMAP_PERIOD_SIZE, //1 ms
268};
269
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700270#define AFE_PROXY_CHANNEL_COUNT 2
271#define AFE_PROXY_SAMPLING_RATE 48000
272
273#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
274#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
275
276struct pcm_config pcm_config_afe_proxy_playback = {
277 .channels = AFE_PROXY_CHANNEL_COUNT,
278 .rate = AFE_PROXY_SAMPLING_RATE,
279 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
280 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
281 .format = PCM_FORMAT_S16_LE,
282 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
283 .stop_threshold = INT_MAX,
284 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
285};
286
287#define AFE_PROXY_RECORD_PERIOD_SIZE 768
288#define AFE_PROXY_RECORD_PERIOD_COUNT 4
289
Aalique Grahame22e49102018-12-18 14:23:57 -0800290struct pcm_config pcm_config_audio_capture_rt = {
291 .channels = 2,
292 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
293 .period_size = ULL_PERIOD_SIZE,
294 .period_count = 512,
295 .format = PCM_FORMAT_S16_LE,
296 .start_threshold = 0,
297 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
298 .silence_threshold = 0,
299 .silence_size = 0,
300 .avail_min = ULL_PERIOD_SIZE, //1 ms
301};
302
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700303struct pcm_config pcm_config_afe_proxy_record = {
304 .channels = AFE_PROXY_CHANNEL_COUNT,
305 .rate = AFE_PROXY_SAMPLING_RATE,
306 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
307 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
308 .format = PCM_FORMAT_S16_LE,
309 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
310 .stop_threshold = INT_MAX,
311 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
312};
313
Ashish Jainf1eaa582016-05-23 20:54:24 +0530314#define AUDIO_MAX_PCM_FORMATS 7
315
316const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
317 [AUDIO_FORMAT_DEFAULT] = 0,
318 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
319 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
320 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
321 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
322 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
323 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
324};
325
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800326const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700327 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
328 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800329 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700330 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
331 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700332 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700333 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700334 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
341 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700342 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
343 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700344 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800345 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700346
Eric Laurentb23d5282013-05-14 15:27:20 -0700347 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700348 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530349 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
350 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
351 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530352 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
353 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700355 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700356 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700357 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700358
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800359 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800360 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400361 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
362 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700363
Derek Chenf7092792017-05-23 12:23:53 -0400364 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700365 [USECASE_VOICE2_CALL] = "voice2-call",
366 [USECASE_VOLTE_CALL] = "volte-call",
367 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800368 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800369 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
370 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800371 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700372 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
373 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
374 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800375 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
376 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
377 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
378
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700379 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
380 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700381 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
382 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700383
384 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
385 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530386 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700387
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530388 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530389 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
390 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700391
392 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
393 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530394 /* For Interactive Audio Streams */
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
401 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
402 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700403
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800404 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
405
Derek Chenf6318be2017-06-12 17:16:24 -0400406 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
407
408 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
409 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
410 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
411 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700412 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530413 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700414};
415
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700416static const audio_usecase_t offload_usecases[] = {
417 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700418 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
419 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
420 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
421 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
422 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700426};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427
Varun Balaraje49253e2017-07-06 19:48:56 +0530428static const audio_usecase_t interactive_usecases[] = {
429 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
430 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
432 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
437};
438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800439#define STRING_TO_ENUM(string) { #string, string }
440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800441struct string_to_enum {
442 const char *name;
443 uint32_t value;
444};
445
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700446static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800447 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800448 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
450 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700455 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
456 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
457 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
458 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
459 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
461 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800466};
467
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700468static const struct string_to_enum formats_name_to_enum_table[] = {
469 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
470 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
471 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700472 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
473 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
474 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700475 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800476 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
477 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700478 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800479};
480
481//list of all supported sample rates by HDMI specification.
482static const int out_hdmi_sample_rates[] = {
483 32000, 44100, 48000, 88200, 96000, 176400, 192000,
484};
485
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700486static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800487 STRING_TO_ENUM(32000),
488 STRING_TO_ENUM(44100),
489 STRING_TO_ENUM(48000),
490 STRING_TO_ENUM(88200),
491 STRING_TO_ENUM(96000),
492 STRING_TO_ENUM(176400),
493 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800494 STRING_TO_ENUM(352800),
495 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700496};
497
Carter Hsu2e429db2019-05-14 18:50:52 +0800498struct in_effect_list {
499 struct listnode list;
500 effect_handle_t handle;
501};
502
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700503static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700504static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700505static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700506//cache last MBDRC cal step level
507static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700508
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530509static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
510static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700511static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800512static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530513static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530514
Derek Chen6f293672019-04-01 01:40:24 -0700515static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
516static void in_snd_mon_cb(void * stream, struct str_parms * parms);
517static void out_snd_mon_cb(void * stream, struct str_parms * parms);
518
Zhou Song331c8e52019-08-26 14:16:12 +0800519static int configure_btsco_sample_rate(snd_device_t snd_device);
520
Vatsal Buchac09ae062018-11-14 13:25:08 +0530521#ifdef AUDIO_FEATURE_ENABLED_GCOV
522extern void __gcov_flush();
523static void enable_gcov()
524{
525 __gcov_flush();
526}
527#else
528static void enable_gcov()
529{
530}
531#endif
532
justinweng20fb6d82019-02-21 18:49:00 -0700533static int in_set_microphone_direction(const struct audio_stream_in *stream,
534 audio_microphone_direction_t dir);
535static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
536
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700537static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
538 int flags __unused)
539{
540 int dir = 0;
541 switch (uc_id) {
542 case USECASE_AUDIO_RECORD_LOW_LATENCY:
543 dir = 1;
544 case USECASE_AUDIO_PLAYBACK_ULL:
545 break;
546 default:
547 return false;
548 }
549
550 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
551 PCM_PLAYBACK : PCM_CAPTURE);
552 if (adev->adm_is_noirq_avail)
553 return adev->adm_is_noirq_avail(adev->adm_data,
554 adev->snd_card, dev_id, dir);
555 return false;
556}
557
558static void register_out_stream(struct stream_out *out)
559{
560 struct audio_device *adev = out->dev;
561 if (is_offload_usecase(out->usecase) ||
562 !adev->adm_register_output_stream)
563 return;
564
565 // register stream first for backward compatibility
566 adev->adm_register_output_stream(adev->adm_data,
567 out->handle,
568 out->flags);
569
570 if (!adev->adm_set_config)
571 return;
572
573 if (out->realtime)
574 adev->adm_set_config(adev->adm_data,
575 out->handle,
576 out->pcm, &out->config);
577}
578
579static void register_in_stream(struct stream_in *in)
580{
581 struct audio_device *adev = in->dev;
582 if (!adev->adm_register_input_stream)
583 return;
584
585 adev->adm_register_input_stream(adev->adm_data,
586 in->capture_handle,
587 in->flags);
588
589 if (!adev->adm_set_config)
590 return;
591
592 if (in->realtime)
593 adev->adm_set_config(adev->adm_data,
594 in->capture_handle,
595 in->pcm,
596 &in->config);
597}
598
599static void request_out_focus(struct stream_out *out, long ns)
600{
601 struct audio_device *adev = out->dev;
602
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700603 if (adev->adm_request_focus_v2)
604 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
605 else if (adev->adm_request_focus)
606 adev->adm_request_focus(adev->adm_data, out->handle);
607}
608
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700609static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700610{
611 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700612 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700613
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700614 if (adev->adm_request_focus_v2_1)
615 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
616 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700617 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
618 else if (adev->adm_request_focus)
619 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700620
621 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700622}
623
624static void release_out_focus(struct stream_out *out)
625{
626 struct audio_device *adev = out->dev;
627
628 if (adev->adm_abandon_focus)
629 adev->adm_abandon_focus(adev->adm_data, out->handle);
630}
631
632static void release_in_focus(struct stream_in *in)
633{
634 struct audio_device *adev = in->dev;
635 if (adev->adm_abandon_focus)
636 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
637}
638
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530639static int parse_snd_card_status(struct str_parms *parms, int *card,
640 card_status_t *status)
641{
642 char value[32]={0};
643 char state[32]={0};
644
645 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
646 if (ret < 0)
647 return -1;
648
649 // sscanf should be okay as value is of max length 32.
650 // same as sizeof state.
651 if (sscanf(value, "%d,%s", card, state) < 2)
652 return -1;
653
654 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
655 CARD_STATUS_OFFLINE;
656 return 0;
657}
658
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700659static inline void adjust_frames_for_device_delay(struct stream_out *out,
660 uint32_t *dsp_frames) {
661 // Adjustment accounts for A2dp encoder latency with offload usecases
662 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800663 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700664 unsigned long offset =
665 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
666 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
667 }
668}
669
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700670static inline bool free_entry(void *key __unused,
671 void *value, void *context __unused)
672{
673 free(value);
674 return true;
675}
676
677static inline void free_map(Hashmap *map)
678{
679 if (map) {
680 hashmapForEach(map, free_entry, (void *) NULL);
681 hashmapFree(map);
682 }
683}
684
685static inline void patch_map_remove(struct audio_device *adev,
686 audio_patch_handle_t patch_handle)
687{
688 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
689 return;
690
691 pthread_mutex_lock(&adev->lock);
692 struct audio_patch_info *p_info =
693 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
694 if (p_info) {
695 ALOGV("%s: Remove patch %d", __func__, patch_handle);
696 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
697 free(p_info->patch);
698 pthread_mutex_destroy(&p_info->lock);
699 free(p_info);
700 }
701 pthread_mutex_unlock(&adev->lock);
702}
703
704static inline int io_streams_map_insert(struct audio_device *adev,
705 struct audio_stream *stream,
706 audio_io_handle_t handle,
707 audio_patch_handle_t patch_handle)
708{
709 struct audio_stream_info *s_info =
710 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
711
712 if (s_info == NULL) {
713 ALOGE("%s: Could not allocate stream info", __func__);
714 return -ENOMEM;
715 }
716 s_info->stream = stream;
717 s_info->patch_handle = patch_handle;
718 pthread_mutex_init(&s_info->lock, (const pthread_mutexattr_t *) NULL);
719
720 pthread_mutex_lock(&adev->lock);
721 struct audio_stream_info *stream_info =
722 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
723 pthread_mutex_unlock(&adev->lock);
724 if (stream_info != NULL)
725 free(stream_info);
726 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
727 return 0;
728}
729
730static inline void io_streams_map_remove(struct audio_device *adev,
731 audio_io_handle_t handle)
732{
733 pthread_mutex_lock(&adev->lock);
734 struct audio_stream_info *s_info =
735 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
736 pthread_mutex_unlock(&adev->lock);
737 if (s_info == NULL)
738 return;
739 ALOGD("%s: Removed stream with handle %d", __func__, handle);
740 patch_map_remove(adev, s_info->patch_handle);
741 pthread_mutex_destroy(&s_info->lock);
742 free(s_info);
743 return;
744}
745
746static struct audio_patch_info* fetch_patch_info(struct audio_device *adev,
747 audio_patch_handle_t handle)
748{
749 struct audio_patch_info *p_info = NULL;
750 pthread_mutex_lock(&adev->lock);
751 p_info = (struct audio_patch_info *)
752 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
753 pthread_mutex_unlock(&adev->lock);
754 return p_info;
755}
756
vivek mehtaa76401a2015-04-24 14:12:15 -0700757__attribute__ ((visibility ("default")))
758bool audio_hw_send_gain_dep_calibration(int level) {
759 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700760 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700761
762 pthread_mutex_lock(&adev_init_lock);
763
764 if (adev != NULL && adev->platform != NULL) {
765 pthread_mutex_lock(&adev->lock);
766 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700767
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530768 // cache level info for any of the use case which
769 // was not started.
770 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700771
vivek mehtaa76401a2015-04-24 14:12:15 -0700772 pthread_mutex_unlock(&adev->lock);
773 } else {
774 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
775 }
776
777 pthread_mutex_unlock(&adev_init_lock);
778
779 return ret_val;
780}
781
Ashish Jain5106d362016-05-11 19:23:33 +0530782static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
783{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800784 bool gapless_enabled = false;
785 const char *mixer_ctl_name = "Compress Gapless Playback";
786 struct mixer_ctl *ctl;
787
788 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700789 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530790
791 /*Disable gapless if its AV playback*/
792 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800793
794 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
795 if (!ctl) {
796 ALOGE("%s: Could not get ctl for mixer cmd - %s",
797 __func__, mixer_ctl_name);
798 return -EINVAL;
799 }
800
801 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
802 ALOGE("%s: Could not set gapless mode %d",
803 __func__, gapless_enabled);
804 return -EINVAL;
805 }
806 return 0;
807}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700808
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700809__attribute__ ((visibility ("default")))
810int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
811 int table_size) {
812 int ret_val = 0;
813 ALOGV("%s: enter ... ", __func__);
814
815 pthread_mutex_lock(&adev_init_lock);
816 if (adev == NULL) {
817 ALOGW("%s: adev is NULL .... ", __func__);
818 goto done;
819 }
820
821 pthread_mutex_lock(&adev->lock);
822 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
823 pthread_mutex_unlock(&adev->lock);
824done:
825 pthread_mutex_unlock(&adev_init_lock);
826 ALOGV("%s: exit ... ", __func__);
827 return ret_val;
828}
829
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800830bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800831{
832 bool ret = false;
833 ALOGV("%s: enter ...", __func__);
834
835 pthread_mutex_lock(&adev_init_lock);
836
837 if (adev != NULL && adev->platform != NULL) {
838 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800839 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800840 pthread_mutex_unlock(&adev->lock);
841 }
842
843 pthread_mutex_unlock(&adev_init_lock);
844
845 ALOGV("%s: exit with ret %d", __func__, ret);
846 return ret;
847}
Aalique Grahame22e49102018-12-18 14:23:57 -0800848
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700849static bool is_supported_format(audio_format_t format)
850{
Eric Laurent86e17132013-09-12 17:49:30 -0700851 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530852 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530853 format == AUDIO_FORMAT_AAC_LC ||
854 format == AUDIO_FORMAT_AAC_HE_V1 ||
855 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530856 format == AUDIO_FORMAT_AAC_ADTS_LC ||
857 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
858 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530859 format == AUDIO_FORMAT_AAC_LATM_LC ||
860 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
861 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530862 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
863 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530864 format == AUDIO_FORMAT_PCM_FLOAT ||
865 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700866 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530867 format == AUDIO_FORMAT_AC3 ||
868 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700869 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530870 format == AUDIO_FORMAT_DTS ||
871 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800872 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530873 format == AUDIO_FORMAT_ALAC ||
874 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530875 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530876 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800877 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530878 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700879 format == AUDIO_FORMAT_APTX ||
880 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800881 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700882
883 return false;
884}
885
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700886static inline bool is_mmap_usecase(audio_usecase_t uc_id)
887{
888 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
889 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
890}
891
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700892static inline bool is_valid_volume(float left, float right)
893{
894 return ((left >= 0.0f && right >= 0.0f) ? true : false);
895}
896
Avinash Vaish71a8b972014-07-24 15:36:33 +0530897static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
898 struct audio_usecase *uc_info)
899{
900 struct listnode *node;
901 struct audio_usecase *usecase;
902
903 if (uc_info == NULL)
904 return -EINVAL;
905
906 /* Re-route all voice usecases on the shared backend other than the
907 specified usecase to new snd devices */
908 list_for_each(node, &adev->usecase_list) {
909 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800910 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530911 enable_audio_route(adev, usecase);
912 }
913 return 0;
914}
915
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530916static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530917{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530918 ALOGV("%s", __func__);
919 audio_route_apply_and_update_path(adev->audio_route,
920 "asrc-mode");
921 adev->asrc_mode_enabled = true;
922}
923
924static void disable_asrc_mode(struct audio_device *adev)
925{
926 ALOGV("%s", __func__);
927 audio_route_reset_and_update_path(adev->audio_route,
928 "asrc-mode");
929 adev->asrc_mode_enabled = false;
930}
931
932/*
933 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
934 * 44.1 or Native DSD backends are enabled for any of current use case.
935 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
936 * - Disable current mix path use case(Headphone backend) and re-enable it with
937 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
938 * e.g. Naitve DSD or Headphone 44.1 -> + 48
939 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530940static void check_and_set_asrc_mode(struct audio_device *adev,
941 struct audio_usecase *uc_info,
942 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530943{
944 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530945 int i, num_new_devices = 0;
946 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
947 /*
948 *Split snd device for new combo use case
949 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
950 */
951 if (platform_split_snd_device(adev->platform,
952 snd_device,
953 &num_new_devices,
954 split_new_snd_devices) == 0) {
955 for (i = 0; i < num_new_devices; i++)
956 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
957 } else {
958 int new_backend_idx = platform_get_backend_index(snd_device);
959 if (((new_backend_idx == HEADPHONE_BACKEND) ||
960 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
961 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
962 !adev->asrc_mode_enabled) {
963 struct listnode *node = NULL;
964 struct audio_usecase *uc = NULL;
965 struct stream_out *curr_out = NULL;
966 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
967 int i, num_devices, ret = 0;
968 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530969
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530970 list_for_each(node, &adev->usecase_list) {
971 uc = node_to_item(node, struct audio_usecase, list);
972 curr_out = (struct stream_out*) uc->stream.out;
973 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
974 /*
975 *Split snd device for existing combo use case
976 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
977 */
978 ret = platform_split_snd_device(adev->platform,
979 uc->out_snd_device,
980 &num_devices,
981 split_snd_devices);
982 if (ret < 0 || num_devices == 0) {
983 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
984 split_snd_devices[0] = uc->out_snd_device;
985 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800986 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530987 for (i = 0; i < num_devices; i++) {
988 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
989 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
990 if((new_backend_idx == HEADPHONE_BACKEND) &&
991 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
992 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
993 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
994 __func__);
995 enable_asrc_mode(adev);
996 break;
997 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
998 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
999 (usecase_backend_idx == HEADPHONE_BACKEND)) {
1000 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
1001 __func__);
1002 disable_audio_route(adev, uc);
1003 disable_snd_device(adev, uc->out_snd_device);
1004 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1005 if (new_backend_idx == DSD_NATIVE_BACKEND)
1006 audio_route_apply_and_update_path(adev->audio_route,
1007 "hph-true-highquality-mode");
1008 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1009 (curr_out->bit_width >= 24))
1010 audio_route_apply_and_update_path(adev->audio_route,
1011 "hph-highquality-mode");
1012 enable_asrc_mode(adev);
1013 enable_snd_device(adev, uc->out_snd_device);
1014 enable_audio_route(adev, uc);
1015 break;
1016 }
1017 }
1018 // reset split devices count
1019 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001020 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301021 if (adev->asrc_mode_enabled)
1022 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301023 }
1024 }
1025 }
1026}
1027
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001028static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1029 struct audio_effect_config effect_config,
1030 unsigned int param_value)
1031{
1032 char mixer_ctl_name[] = "Audio Effect";
1033 struct mixer_ctl *ctl;
1034 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001035 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001036
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001037 if (in == NULL) {
1038 ALOGE("%s: active input stream is NULL", __func__);
1039 return -EINVAL;
1040 }
1041
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001042 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1043 if (!ctl) {
1044 ALOGE("%s: Could not get mixer ctl - %s",
1045 __func__, mixer_ctl_name);
1046 return -EINVAL;
1047 }
1048
1049 set_values[0] = 1; //0:Rx 1:Tx
1050 set_values[1] = in->app_type_cfg.app_type;
1051 set_values[2] = (long)effect_config.module_id;
1052 set_values[3] = (long)effect_config.instance_id;
1053 set_values[4] = (long)effect_config.param_id;
1054 set_values[5] = param_value;
1055
1056 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1057
1058 return 0;
1059
1060}
1061
1062static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1063 int effect_type, unsigned int *param_value)
1064{
1065 int ret = 0;
1066 struct audio_effect_config other_effect_config;
1067 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001068 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001069
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001070 if (in == NULL) {
1071 ALOGE("%s: active input stream is NULL", __func__);
1072 return -EINVAL;
1073 }
1074
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001075 usecase = get_usecase_from_list(adev, in->usecase);
1076 if (!usecase)
1077 return -EINVAL;
1078
1079 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1080 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1081 if (ret < 0) {
1082 ALOGE("%s Failed to get effect params %d", __func__, ret);
1083 return ret;
1084 }
1085
1086 if (module_id == other_effect_config.module_id) {
1087 //Same module id for AEC/NS. Values need to be combined
1088 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1089 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1090 *param_value |= other_effect_config.param_value;
1091 }
1092 }
1093
1094 return ret;
1095}
1096
1097static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301098{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001099 struct audio_effect_config effect_config;
1100 struct audio_usecase *usecase = NULL;
1101 int ret = 0;
1102 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001103 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001104
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001105 if(!voice_extn_is_dynamic_ecns_enabled())
1106 return ENOSYS;
1107
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001108 if (!in) {
1109 ALOGE("%s: Invalid input stream", __func__);
1110 return -EINVAL;
1111 }
1112
1113 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1114
1115 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001116 if (usecase == NULL) {
1117 ALOGE("%s: Could not find the usecase (%d) in the list",
1118 __func__, in->usecase);
1119 return -EINVAL;
1120 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001121
1122 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1123 if (ret < 0) {
1124 ALOGE("%s Failed to get module id %d", __func__, ret);
1125 return ret;
1126 }
1127 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1128 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1129
1130 if(enable)
1131 param_value = effect_config.param_value;
1132
1133 /*Special handling for AEC & NS effects Param values need to be
1134 updated if module ids are same*/
1135
1136 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1137 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1138 if (ret < 0)
1139 return ret;
1140 }
1141
1142 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1143
1144 return ret;
1145}
1146
1147static void check_and_enable_effect(struct audio_device *adev)
1148{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001149 if(!voice_extn_is_dynamic_ecns_enabled())
1150 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001151
Eric Laurent637e2d42018-11-15 12:24:31 -08001152 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001153
Eric Laurent637e2d42018-11-15 12:24:31 -08001154 if (in != NULL && !in->standby) {
1155 if (in->enable_aec)
1156 enable_disable_effect(adev, EFFECT_AEC, true);
1157
1158 if (in->enable_ns &&
1159 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1160 enable_disable_effect(adev, EFFECT_NS, true);
1161 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001162 }
1163}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001164
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001165int pcm_ioctl(struct pcm *pcm, int request, ...)
1166{
1167 va_list ap;
1168 void * arg;
1169 int pcm_fd = *(int*)pcm;
1170
1171 va_start(ap, request);
1172 arg = va_arg(ap, void *);
1173 va_end(ap);
1174
1175 return ioctl(pcm_fd, request, arg);
1176}
1177
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001178int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001179 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001180{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001181 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001182 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301183 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301184 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001185 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301186 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001187
1188 if (usecase == NULL)
1189 return -EINVAL;
1190
1191 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1192
Carter Hsu2e429db2019-05-14 18:50:52 +08001193 if (usecase->type == PCM_CAPTURE) {
1194 struct stream_in *in = usecase->stream.in;
1195 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001196 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001197
1198 if (in) {
1199 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001200 list_init(&out_devices);
1201 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001202 struct listnode *node;
1203 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1204 USECASE_AUDIO_PLAYBACK_VOIP);
1205 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001206 assign_devices(&out_devices,
1207 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001208 } else if (adev->primary_output &&
1209 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001210 assign_devices(&out_devices,
1211 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001212 } else {
1213 list_for_each(node, &adev->usecase_list) {
1214 uinfo = node_to_item(node, struct audio_usecase, list);
1215 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001216 assign_devices(&out_devices,
1217 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001218 break;
1219 }
1220 }
1221 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001222
1223 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001224 in->ec_opened = true;
1225 }
1226 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001227 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1228 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1229 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001230 snd_device = usecase->in_snd_device;
1231 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001232 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001233 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001234
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001235#ifdef DS1_DOLBY_DAP_ENABLED
1236 audio_extn_dolby_set_dmid(adev);
1237 audio_extn_dolby_set_endpoint(adev);
1238#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001239 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001240 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301241 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001242 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001243 if (audio_extn_is_maxx_audio_enabled())
1244 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301245 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301246 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1247 out = usecase->stream.out;
1248 if (out && out->compr)
1249 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1250 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301251
1252 if (usecase->type == PCM_CAPTURE) {
1253 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001254 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301255 ALOGD("%s: set custom mtmx params v1", __func__);
1256 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1257 }
1258 } else {
1259 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1260 }
Manish Dewangan58229382017-02-02 15:48:41 +05301261
Andy Hung756ecc12018-10-19 17:47:12 -07001262 // we shouldn't truncate mixer_path
1263 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1264 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1265 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001266 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001267 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301268 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1269 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1270 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1271 if (parms) {
1272 audio_extn_fm_set_parameters(adev, parms);
1273 str_parms_destroy(parms);
1274 }
1275 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001276 ALOGV("%s: exit", __func__);
1277 return 0;
1278}
1279
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001280int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001281 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001283 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001284 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301285 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001286
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301287 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001288 return -EINVAL;
1289
1290 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301291 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001292 snd_device = usecase->in_snd_device;
1293 else
1294 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001295 // we shouldn't truncate mixer_path
1296 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1297 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1298 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001299 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001300 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001301 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001302 if (usecase->type == PCM_CAPTURE) {
1303 struct stream_in *in = usecase->stream.in;
1304 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001305 struct listnode out_devices;
1306 list_init(&out_devices);
1307 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001308 in->ec_opened = false;
1309 }
1310 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001311 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301312 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301313
1314 if (usecase->type == PCM_CAPTURE) {
1315 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001316 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301317 ALOGD("%s: reset custom mtmx params v1", __func__);
1318 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1319 }
1320 } else {
1321 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1322 }
1323
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001324 if ((usecase->type == PCM_PLAYBACK) &&
1325 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301326 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301327
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001328 ALOGV("%s: exit", __func__);
1329 return 0;
1330}
1331
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001332int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001333 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001334{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301335 int i, num_devices = 0;
1336 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001337 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1338
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001339 if (snd_device < SND_DEVICE_MIN ||
1340 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001341 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001342 return -EINVAL;
1343 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001344
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001345 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001346 ALOGE("%s: Invalid sound device returned", __func__);
1347 return -EINVAL;
1348 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001349
1350 adev->snd_dev_ref_cnt[snd_device]++;
1351
1352 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1353 (platform_split_snd_device(adev->platform,
1354 snd_device,
1355 &num_devices,
1356 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001357 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001358 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001359 return 0;
1360 }
1361
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001362 if (audio_extn_spkr_prot_is_enabled())
1363 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001364
Aalique Grahame22e49102018-12-18 14:23:57 -08001365 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1366
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001367 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1368 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001369 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1370 goto err;
1371 }
1372 audio_extn_dev_arbi_acquire(snd_device);
1373 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001374 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001375 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001376 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001377 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001378 } else if (platform_split_snd_device(adev->platform,
1379 snd_device,
1380 &num_devices,
1381 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301382 for (i = 0; i < num_devices; i++) {
1383 enable_snd_device(adev, new_snd_devices[i]);
1384 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001385 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001386 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001387 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301388
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301389
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001390 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1391 (audio_extn_a2dp_start_playback() < 0)) {
1392 ALOGE(" fail to configure A2dp Source control path ");
1393 goto err;
1394 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001395
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001396 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1397 (audio_extn_a2dp_start_capture() < 0)) {
1398 ALOGE(" fail to configure A2dp Sink control path ");
1399 goto err;
1400 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301401
Zhou Song12c29502019-03-16 10:37:18 +08001402 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1403 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1404 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1405 (audio_extn_sco_start_configuration() < 0)) {
1406 ALOGE(" fail to configure sco control path ");
1407 goto err;
1408 }
1409
Zhou Song331c8e52019-08-26 14:16:12 +08001410 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001411 /* due to the possibility of calibration overwrite between listen
1412 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001413 audio_extn_sound_trigger_update_device_status(snd_device,
1414 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301415 audio_extn_listen_update_device_status(snd_device,
1416 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001417 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001418 audio_extn_sound_trigger_update_device_status(snd_device,
1419 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301420 audio_extn_listen_update_device_status(snd_device,
1421 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001422 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001423 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001424 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001425 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301426
1427 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1428 !adev->native_playback_enabled &&
1429 audio_is_true_native_stream_active(adev)) {
1430 ALOGD("%s: %d: napb: enabling native mode in hardware",
1431 __func__, __LINE__);
1432 audio_route_apply_and_update_path(adev->audio_route,
1433 "true-native-mode");
1434 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301435 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301436 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1437 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001438 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001439 ALOGD("%s: init ec ref loopback", __func__);
1440 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1441 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001444err:
1445 adev->snd_dev_ref_cnt[snd_device]--;
1446 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001447}
1448
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001449int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001450 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301452 int i, num_devices = 0;
1453 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001454 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1455
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001456 if (snd_device < SND_DEVICE_MIN ||
1457 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001458 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001459 return -EINVAL;
1460 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001461
1462 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1463 ALOGE("%s: Invalid sound device returned", __func__);
1464 return -EINVAL;
1465 }
1466
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1468 ALOGE("%s: device ref cnt is already 0", __func__);
1469 return -EINVAL;
1470 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001471
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001472 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001473
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001474
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001476 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301477
Aalique Grahame22e49102018-12-18 14:23:57 -08001478 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1479
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001480 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1481 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001482 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001483
1484 // when speaker device is disabled, reset swap.
1485 // will be renabled on usecase start
1486 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001487 } else if (platform_split_snd_device(adev->platform,
1488 snd_device,
1489 &num_devices,
1490 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301491 for (i = 0; i < num_devices; i++) {
1492 disable_snd_device(adev, new_snd_devices[i]);
1493 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001494 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001495 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001496 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001497 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001498
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001499 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301500 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001501 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001502 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001503 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001504 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301505 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001506 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301507 adev->native_playback_enabled) {
1508 ALOGD("%s: %d: napb: disabling native mode in hardware",
1509 __func__, __LINE__);
1510 audio_route_reset_and_update_path(adev->audio_route,
1511 "true-native-mode");
1512 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001513 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301514 adev->asrc_mode_enabled) {
1515 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301516 disable_asrc_mode(adev);
1517 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001518 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301519 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001520 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001521 ALOGD("%s: deinit ec ref loopback", __func__);
1522 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1523 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001524
1525 audio_extn_utils_release_snd_device(snd_device);
1526 } else {
1527 if (platform_split_snd_device(adev->platform,
1528 snd_device,
1529 &num_devices,
1530 new_snd_devices) == 0) {
1531 for (i = 0; i < num_devices; i++) {
1532 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1533 }
1534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001536
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537 return 0;
1538}
1539
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001540/*
1541 legend:
1542 uc - existing usecase
1543 new_uc - new usecase
1544 d1, d11, d2 - SND_DEVICE enums
1545 a1, a2 - corresponding ANDROID device enums
1546 B1, B2 - backend strings
1547
1548case 1
1549 uc->dev d1 (a1) B1
1550 new_uc->dev d1 (a1), d2 (a2) B1, B2
1551
1552 resolution: disable and enable uc->dev on d1
1553
1554case 2
1555 uc->dev d1 (a1) B1
1556 new_uc->dev d11 (a1) B1
1557
1558 resolution: need to switch uc since d1 and d11 are related
1559 (e.g. speaker and voice-speaker)
1560 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1561
1562case 3
1563 uc->dev d1 (a1) B1
1564 new_uc->dev d2 (a2) B2
1565
1566 resolution: no need to switch uc
1567
1568case 4
1569 uc->dev d1 (a1) B1
1570 new_uc->dev d2 (a2) B1
1571
1572 resolution: disable enable uc-dev on d2 since backends match
1573 we cannot enable two streams on two different devices if they
1574 share the same backend. e.g. if offload is on speaker device using
1575 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1576 using the same backend, offload must also be switched to voice-handset.
1577
1578case 5
1579 uc->dev d1 (a1) B1
1580 new_uc->dev d1 (a1), d2 (a2) B1
1581
1582 resolution: disable enable uc-dev on d2 since backends match
1583 we cannot enable two streams on two different devices if they
1584 share the same backend.
1585
1586case 6
1587 uc->dev d1 (a1) B1
1588 new_uc->dev d2 (a1) B2
1589
1590 resolution: no need to switch
1591
1592case 7
1593 uc->dev d1 (a1), d2 (a2) B1, B2
1594 new_uc->dev d1 (a1) B1
1595
1596 resolution: no need to switch
1597
Zhou Song4ba65882018-07-09 14:48:07 +08001598case 8
1599 uc->dev d1 (a1) B1
1600 new_uc->dev d11 (a1), d2 (a2) B1, B2
1601 resolution: compared to case 1, for this case, d1 and d11 are related
1602 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001603*/
1604static snd_device_t derive_playback_snd_device(void * platform,
1605 struct audio_usecase *uc,
1606 struct audio_usecase *new_uc,
1607 snd_device_t new_snd_device)
1608{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001609 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001610
1611 snd_device_t d1 = uc->out_snd_device;
1612 snd_device_t d2 = new_snd_device;
1613
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001614 list_init(&a1);
1615 list_init(&a2);
1616
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301617 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301618 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001619 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1620 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301621 break;
1622 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001623 assign_devices(&a1, &uc->stream.out->device_list);
1624 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301625 break;
1626 }
1627
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001628 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001629 if (!compare_devices(&a1, &a2) &&
1630 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001631 snd_device_t d3[2];
1632 int num_devices = 0;
1633 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001634 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001635 &num_devices,
1636 d3);
1637 if (ret < 0) {
1638 if (ret != -ENOSYS) {
1639 ALOGW("%s failed to split snd_device %d",
1640 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001641 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001642 }
1643 goto end;
1644 }
1645
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001646 if (platform_check_backends_match(d3[0], d3[1])) {
1647 return d2; // case 5
1648 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001649 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301650 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001651 // check if d1 is related to any of d3's
1652 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001653 return d1; // case 1
1654 else
1655 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001656 }
1657 } else {
1658 if (platform_check_backends_match(d1, d2)) {
1659 return d2; // case 2, 4
1660 } else {
1661 return d1; // case 6, 3
1662 }
1663 }
1664
1665end:
1666 return d2; // return whatever was calculated before.
1667}
1668
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001669static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301670 struct audio_usecase *uc_info,
1671 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001672{
1673 struct listnode *node;
1674 struct audio_usecase *usecase;
1675 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301676 snd_device_t uc_derive_snd_device;
1677 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001678 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1679 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001680 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301681 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001682 /*
1683 * This function is to make sure that all the usecases that are active on
1684 * the hardware codec backend are always routed to any one device that is
1685 * handled by the hardware codec.
1686 * For example, if low-latency and deep-buffer usecases are currently active
1687 * on speaker and out_set_parameters(headset) is received on low-latency
1688 * output, then we have to make sure deep-buffer is also switched to headset,
1689 * because of the limitation that both the devices cannot be enabled
1690 * at the same time as they share the same backend.
1691 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001692 /*
1693 * This call is to check if we need to force routing for a particular stream
1694 * If there is a backend configuration change for the device when a
1695 * new stream starts, then ADM needs to be closed and re-opened with the new
1696 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001697 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001698 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001699 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1700 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301701 /* For a2dp device reconfigure all active sessions
1702 * with new AFE encoder format based on a2dp state
1703 */
1704 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1705 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1706 audio_extn_a2dp_is_force_device_switch()) {
1707 force_routing = true;
1708 force_restart_session = true;
1709 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301710 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1711
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001713 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001714 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001715 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1716 switch_device[i] = false;
1717
1718 list_for_each(node, &adev->usecase_list) {
1719 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001720
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301721 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1722 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301723 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301724 platform_get_snd_device_name(usecase->out_snd_device),
1725 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301726 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1727 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301728 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1729 usecase, uc_info, snd_device);
1730 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001731 (is_codec_backend_out_device_type(&usecase->device_list) ||
1732 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1733 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1734 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1735 is_a2dp_out_device_type(&usecase->device_list) ||
1736 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301737 ((force_restart_session) ||
1738 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301739 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1740 __func__, use_case_table[usecase->id],
1741 platform_get_snd_device_name(usecase->out_snd_device));
1742 disable_audio_route(adev, usecase);
1743 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301744 /* Enable existing usecase on derived playback device */
1745 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301746 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301747 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001748 }
1749 }
1750
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301751 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1752 num_uc_to_switch);
1753
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001754 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001755 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001756
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301757 /* Make sure the previous devices to be disabled first and then enable the
1758 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001759 list_for_each(node, &adev->usecase_list) {
1760 usecase = node_to_item(node, struct audio_usecase, list);
1761 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001762 /* Check if output sound device to be switched can be split and if any
1763 of the split devices match with derived sound device */
1764 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1765 &num_devices, split_snd_devices) == 0) {
1766 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1767 for (i = 0; i < num_devices; i++) {
1768 /* Disable devices that do not match with derived sound device */
1769 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1770 disable_snd_device(adev, split_snd_devices[i]);
1771 }
1772 } else {
1773 disable_snd_device(adev, usecase->out_snd_device);
1774 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001775 }
1776 }
1777
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001778 list_for_each(node, &adev->usecase_list) {
1779 usecase = node_to_item(node, struct audio_usecase, list);
1780 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001781 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1782 &num_devices, split_snd_devices) == 0) {
1783 /* Enable derived sound device only if it does not match with
1784 one of the split sound devices. This is because the matching
1785 sound device was not disabled */
1786 bool should_enable = true;
1787 for (i = 0; i < num_devices; i++) {
1788 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1789 should_enable = false;
1790 break;
1791 }
1792 }
1793 if (should_enable)
1794 enable_snd_device(adev, derive_snd_device[usecase->id]);
1795 } else {
1796 enable_snd_device(adev, derive_snd_device[usecase->id]);
1797 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001798 }
1799 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001800
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001801 /* Re-route all the usecases on the shared backend other than the
1802 specified usecase to new snd devices */
1803 list_for_each(node, &adev->usecase_list) {
1804 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301805 /* Update the out_snd_device only before enabling the audio route */
1806 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301807 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301808 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301809 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301810 use_case_table[usecase->id],
1811 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001812 /* Update voc calibration before enabling VoIP route */
1813 if (usecase->type == VOIP_CALL)
1814 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001815 usecase->out_snd_device,
1816 platform_get_input_snd_device(
1817 adev->platform, NULL,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001818 &uc_info->device_list));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301819 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301820 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001821 out_set_voip_volume(&usecase->stream.out->stream,
1822 usecase->stream.out->volume_l,
1823 usecase->stream.out->volume_r);
1824 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301825 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001826 }
1827 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001828 }
1829}
1830
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301831static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001832 struct audio_usecase *uc_info,
1833 snd_device_t snd_device)
1834{
1835 struct listnode *node;
1836 struct audio_usecase *usecase;
1837 bool switch_device[AUDIO_USECASE_MAX];
1838 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001839 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001840 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001841
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301842 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1843 snd_device);
1844 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301845
1846 /*
1847 * Make sure out devices is checked against out codec backend device and
1848 * also in devices against in codec backend. Checking out device against in
1849 * codec backend or vice versa causes issues.
1850 */
1851 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001852 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001853 /*
1854 * This function is to make sure that all the active capture usecases
1855 * are always routed to the same input sound device.
1856 * For example, if audio-record and voice-call usecases are currently
1857 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1858 * is received for voice call then we have to make sure that audio-record
1859 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1860 * because of the limitation that two devices cannot be enabled
1861 * at the same time if they share the same backend.
1862 */
1863 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1864 switch_device[i] = false;
1865
1866 list_for_each(node, &adev->usecase_list) {
1867 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301868 /*
1869 * TODO: Enhance below condition to handle BT sco/USB multi recording
1870 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001871 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001872 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301873 (usecase->in_snd_device != snd_device || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001874 ((backend_check_cond &&
1875 (is_codec_backend_in_device_type(&usecase->device_list) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301876 (usecase->type == VOIP_CALL))) &&
Carter Hsu1d2a0532018-10-04 09:24:36 +08001877 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001878 is_single_device_type_equal(&usecase->device_list,
1879 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001880 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001881 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001882 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001883 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1884 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001885 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001886 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001887 switch_device[usecase->id] = true;
1888 num_uc_to_switch++;
1889 }
1890 }
1891
1892 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001893 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001894
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301895 /* Make sure the previous devices to be disabled first and then enable the
1896 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001897 list_for_each(node, &adev->usecase_list) {
1898 usecase = node_to_item(node, struct audio_usecase, list);
1899 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001900 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001901 }
1902 }
1903
1904 list_for_each(node, &adev->usecase_list) {
1905 usecase = node_to_item(node, struct audio_usecase, list);
1906 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001907 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001908 }
1909 }
1910
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001911 /* Re-route all the usecases on the shared backend other than the
1912 specified usecase to new snd devices */
1913 list_for_each(node, &adev->usecase_list) {
1914 usecase = node_to_item(node, struct audio_usecase, list);
1915 /* Update the in_snd_device only before enabling the audio route */
1916 if (switch_device[usecase->id] ) {
1917 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001918 if (usecase->type != VOICE_CALL) {
1919 /* Update voc calibration before enabling VoIP route */
1920 if (usecase->type == VOIP_CALL)
1921 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001922 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001923 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301924 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001925 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001926 }
1927 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001928 }
1929}
1930
Mingming Yin3a941d42016-02-17 18:08:05 -08001931static void reset_hdmi_sink_caps(struct stream_out *out) {
1932 int i = 0;
1933
1934 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1935 out->supported_channel_masks[i] = 0;
1936 }
1937 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1938 out->supported_formats[i] = 0;
1939 }
1940 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1941 out->supported_sample_rates[i] = 0;
1942 }
1943}
1944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001945/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001946static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947{
Mingming Yin3a941d42016-02-17 18:08:05 -08001948 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001949 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
1950 out->extconn.cs.controller,
1951 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952
Mingming Yin3a941d42016-02-17 18:08:05 -08001953 reset_hdmi_sink_caps(out);
1954
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001955 /* Cache ext disp type */
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001956 if (platform_get_ext_disp_type_v2(adev->platform,
1957 out->extconn.cs.controller,
1958 out->extconn.cs.stream <= 0)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001959 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001960 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001961 }
1962
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001965 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001966 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001967 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1968 case 6:
1969 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1970 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1971 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1972 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1973 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1974 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975 break;
1976 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001977 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001978 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979 break;
1980 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001981
1982 // check channel format caps
1983 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001984 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
1985 out->extconn.cs.controller,
1986 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08001987 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1988 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1989 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1990 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1991 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1992 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1993 }
1994
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001995 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
1996 out->extconn.cs.controller,
1997 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07001998 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1999 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2000 }
2001
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002002 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2003 out->extconn.cs.controller,
2004 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002005 ALOGV(":%s HDMI supports DTS format", __func__);
2006 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2007 }
2008
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002009 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2010 out->extconn.cs.controller,
2011 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002012 ALOGV(":%s HDMI supports DTS HD format", __func__);
2013 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2014 }
2015
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002016 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2017 out->extconn.cs.controller,
2018 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002019 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2020 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2021 }
2022
Mingming Yin3a941d42016-02-17 18:08:05 -08002023
2024 // check sample rate caps
2025 i = 0;
2026 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002027 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2028 out->extconn.cs.controller,
2029 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002030 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2031 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2032 }
2033 }
2034
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002035 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036}
2037
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002038static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2039 uint32_t *supported_sample_rates __unused,
2040 uint32_t max_rates __unused)
2041{
2042 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2043 supported_sample_rates,
2044 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302045 ssize_t i = 0;
2046
2047 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002048 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2049 supported_sample_rates[i]);
2050 }
2051 return count;
2052}
2053
2054static inline int read_usb_sup_channel_masks(bool is_playback,
2055 audio_channel_mask_t *supported_channel_masks,
2056 uint32_t max_masks)
2057{
2058 int channels = audio_extn_usb_get_max_channels(is_playback);
2059 int channel_count;
2060 uint32_t num_masks = 0;
2061 if (channels > MAX_HIFI_CHANNEL_COUNT)
2062 channels = MAX_HIFI_CHANNEL_COUNT;
2063
2064 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002065 // start from 2 channels as framework currently doesn't support mono.
2066 if (channels >= FCC_2) {
2067 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2068 }
2069 for (channel_count = FCC_2;
2070 channel_count <= channels && num_masks < max_masks;
2071 ++channel_count) {
2072 supported_channel_masks[num_masks++] =
2073 audio_channel_mask_for_index_assignment_from_count(channel_count);
2074 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002075 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002076 // For capture we report all supported channel masks from 1 channel up.
2077 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002078 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2079 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002080 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2081 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2082 if (channel_count <= FCC_2) {
2083 mask = audio_channel_in_mask_from_count(channel_count);
2084 supported_channel_masks[num_masks++] = mask;
2085 }
2086 const audio_channel_mask_t index_mask =
2087 audio_channel_mask_for_index_assignment_from_count(channel_count);
2088 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2089 supported_channel_masks[num_masks++] = index_mask;
2090 }
2091 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002092 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302093
vincenttewf51c94e2019-05-07 10:28:53 +08002094 for (size_t i = 0; i < num_masks; ++i) {
2095 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2096 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302097 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002098 return num_masks;
2099}
2100
2101static inline int read_usb_sup_formats(bool is_playback __unused,
2102 audio_format_t *supported_formats,
2103 uint32_t max_formats __unused)
2104{
2105 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2106 switch (bitwidth) {
2107 case 24:
2108 // XXX : usb.c returns 24 for s24 and s24_le?
2109 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2110 break;
2111 case 32:
2112 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2113 break;
2114 case 16:
2115 default :
2116 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2117 break;
2118 }
2119 ALOGV("%s: %s supported format %d", __func__,
2120 is_playback ? "P" : "C", bitwidth);
2121 return 1;
2122}
2123
2124static inline int read_usb_sup_params_and_compare(bool is_playback,
2125 audio_format_t *format,
2126 audio_format_t *supported_formats,
2127 uint32_t max_formats,
2128 audio_channel_mask_t *mask,
2129 audio_channel_mask_t *supported_channel_masks,
2130 uint32_t max_masks,
2131 uint32_t *rate,
2132 uint32_t *supported_sample_rates,
2133 uint32_t max_rates) {
2134 int ret = 0;
2135 int num_formats;
2136 int num_masks;
2137 int num_rates;
2138 int i;
2139
2140 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2141 max_formats);
2142 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2143 max_masks);
2144
2145 num_rates = read_usb_sup_sample_rates(is_playback,
2146 supported_sample_rates, max_rates);
2147
2148#define LUT(table, len, what, dflt) \
2149 for (i=0; i<len && (table[i] != what); i++); \
2150 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2151
2152 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2153 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2154 LUT(supported_sample_rates, num_rates, *rate, 0);
2155
2156#undef LUT
2157 return ret < 0 ? -EINVAL : 0; // HACK TBD
2158}
2159
Alexy Josephb1379942016-01-29 15:49:38 -08002160audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002161 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002162{
2163 struct audio_usecase *usecase;
2164 struct listnode *node;
2165
2166 list_for_each(node, &adev->usecase_list) {
2167 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002168 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002169 ALOGV("%s: usecase id %d", __func__, usecase->id);
2170 return usecase->id;
2171 }
2172 }
2173 return USECASE_INVALID;
2174}
2175
Alexy Josephb1379942016-01-29 15:49:38 -08002176struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002177 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002178{
2179 struct audio_usecase *usecase;
2180 struct listnode *node;
2181
2182 list_for_each(node, &adev->usecase_list) {
2183 usecase = node_to_item(node, struct audio_usecase, list);
2184 if (usecase->id == uc_id)
2185 return usecase;
2186 }
2187 return NULL;
2188}
2189
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302190/*
2191 * is a true native playback active
2192 */
2193bool audio_is_true_native_stream_active(struct audio_device *adev)
2194{
2195 bool active = false;
2196 int i = 0;
2197 struct listnode *node;
2198
2199 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2200 ALOGV("%s:napb: not in true mode or non hdphones device",
2201 __func__);
2202 active = false;
2203 goto exit;
2204 }
2205
2206 list_for_each(node, &adev->usecase_list) {
2207 struct audio_usecase *uc;
2208 uc = node_to_item(node, struct audio_usecase, list);
2209 struct stream_out *curr_out =
2210 (struct stream_out*) uc->stream.out;
2211
2212 if (curr_out && PCM_PLAYBACK == uc->type) {
2213 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2214 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2215 uc->id, curr_out->sample_rate,
2216 curr_out->bit_width,
2217 platform_get_snd_device_name(uc->out_snd_device));
2218
2219 if (is_offload_usecase(uc->id) &&
2220 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2221 active = true;
2222 ALOGD("%s:napb:native stream detected", __func__);
2223 }
2224 }
2225 }
2226exit:
2227 return active;
2228}
2229
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002230uint32_t adev_get_dsp_bit_width_enforce_mode()
2231{
2232 if (adev == NULL) {
2233 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2234 return 0;
2235 }
2236 return adev->dsp_bit_width_enforce_mode;
2237}
2238
2239static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2240{
2241 char value[PROPERTY_VALUE_MAX];
2242 int trial;
2243 uint32_t dsp_bit_width_enforce_mode = 0;
2244
2245 if (!mixer) {
2246 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2247 __func__);
2248 return 0;
2249 }
2250
2251 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2252 value, NULL) > 0) {
2253 trial = atoi(value);
2254 switch (trial) {
2255 case 16:
2256 dsp_bit_width_enforce_mode = 16;
2257 break;
2258 case 24:
2259 dsp_bit_width_enforce_mode = 24;
2260 break;
2261 case 32:
2262 dsp_bit_width_enforce_mode = 32;
2263 break;
2264 default:
2265 dsp_bit_width_enforce_mode = 0;
2266 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2267 break;
2268 }
2269 }
2270
2271 return dsp_bit_width_enforce_mode;
2272}
2273
2274static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2275 uint32_t enforce_mode,
2276 bool enable)
2277{
2278 struct mixer_ctl *ctl = NULL;
2279 const char *mixer_ctl_name = "ASM Bit Width";
2280 uint32_t asm_bit_width_mode = 0;
2281
2282 if (enforce_mode == 0) {
2283 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2284 return;
2285 }
2286
2287 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2288 if (!ctl) {
2289 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2290 __func__, mixer_ctl_name);
2291 return;
2292 }
2293
2294 if (enable)
2295 asm_bit_width_mode = enforce_mode;
2296 else
2297 asm_bit_width_mode = 0;
2298
2299 ALOGV("%s DSP bit width feature status is %d width=%d",
2300 __func__, enable, asm_bit_width_mode);
2301 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2302 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2303 asm_bit_width_mode);
2304
2305 return;
2306}
2307
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302308/*
2309 * if native DSD playback active
2310 */
2311bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2312{
2313 bool active = false;
2314 struct listnode *node = NULL;
2315 struct audio_usecase *uc = NULL;
2316 struct stream_out *curr_out = NULL;
2317
2318 list_for_each(node, &adev->usecase_list) {
2319 uc = node_to_item(node, struct audio_usecase, list);
2320 curr_out = (struct stream_out*) uc->stream.out;
2321
2322 if (curr_out && PCM_PLAYBACK == uc->type &&
2323 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2324 active = true;
2325 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302326 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302327 }
2328 }
2329 return active;
2330}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302331
2332static bool force_device_switch(struct audio_usecase *usecase)
2333{
2334 bool ret = false;
2335 bool is_it_true_mode = false;
2336
Zhou Song30f2c3e2018-02-08 14:02:15 +08002337 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302338 usecase->type == TRANSCODE_LOOPBACK_RX ||
2339 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002340 return false;
2341 }
2342
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002343 if(usecase->stream.out == NULL) {
2344 ALOGE("%s: stream.out is NULL", __func__);
2345 return false;
2346 }
2347
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302348 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002349 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002350 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2351 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302352 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2353 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2354 (!is_it_true_mode && adev->native_playback_enabled)){
2355 ret = true;
2356 ALOGD("napb: time to toggle native mode");
2357 }
2358 }
2359
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302360 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302361 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2362 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002363 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302364 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302365 ALOGD("Force a2dp device switch to update new encoder config");
2366 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002367 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302368
Florian Pfister1a84f312018-07-19 14:38:18 +02002369 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302370 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2371 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002372 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302373 return ret;
2374}
2375
Aalique Grahame22e49102018-12-18 14:23:57 -08002376static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2377{
2378 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2379}
2380
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302381bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2382{
2383 bool ret=false;
2384 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002385 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2386 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302387 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2388 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002389 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302390 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2391 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2392 ret = true;
2393
2394 return ret;
2395}
2396
2397bool is_a2dp_device(snd_device_t out_snd_device)
2398{
2399 bool ret=false;
2400 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2401 ret = true;
2402
2403 return ret;
2404}
2405
2406bool is_bt_soc_on(struct audio_device *adev)
2407{
2408 struct mixer_ctl *ctl;
2409 char *mixer_ctl_name = "BT SOC status";
2410 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2411 bool bt_soc_status = true;
2412 if (!ctl) {
2413 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2414 __func__, mixer_ctl_name);
2415 /*This is to ensure we dont break targets which dont have the kernel change*/
2416 return true;
2417 }
2418 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2419 ALOGD("BT SOC status: %d",bt_soc_status);
2420 return bt_soc_status;
2421}
2422
Zhou Song331c8e52019-08-26 14:16:12 +08002423static int configure_btsco_sample_rate(snd_device_t snd_device)
2424{
2425 struct mixer_ctl *ctl = NULL;
2426 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2427 char *rate_str = NULL;
2428 bool is_rx_dev = true;
2429
2430 if (is_btsco_device(snd_device, snd_device)) {
2431 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2432 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2433 if (!ctl_sr_tx || !ctl_sr_rx) {
2434 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2435 if (!ctl_sr)
2436 return -ENOSYS;
2437 }
2438
2439 switch (snd_device) {
2440 case SND_DEVICE_OUT_BT_SCO:
2441 rate_str = "KHZ_8";
2442 break;
2443 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2444 case SND_DEVICE_IN_BT_SCO_MIC:
2445 rate_str = "KHZ_8";
2446 is_rx_dev = false;
2447 break;
2448 case SND_DEVICE_OUT_BT_SCO_WB:
2449 rate_str = "KHZ_16";
2450 break;
2451 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2452 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2453 rate_str = "KHZ_16";
2454 is_rx_dev = false;
2455 break;
2456 default:
2457 return 0;
2458 }
2459
2460 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2461 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2462 return -ENOSYS;
2463 }
2464 return 0;
2465}
2466
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302467int out_standby_l(struct audio_stream *stream);
2468
Eric Laurent637e2d42018-11-15 12:24:31 -08002469struct stream_in *adev_get_active_input(const struct audio_device *adev)
2470{
2471 struct listnode *node;
2472 struct stream_in *last_active_in = NULL;
2473
2474 /* Get last added active input.
2475 * TODO: We may use a priority mechanism to pick highest priority active source */
2476 list_for_each(node, &adev->usecase_list)
2477 {
2478 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2479 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2480 last_active_in = usecase->stream.in;
2481 }
2482
2483 return last_active_in;
2484}
2485
2486struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2487{
2488 struct listnode *node;
2489
2490 /* First check active inputs with voice communication source and then
2491 * any input if audio mode is in communication */
2492 list_for_each(node, &adev->usecase_list)
2493 {
2494 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2495 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2496 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2497 return usecase->stream.in;
2498 }
2499 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2500 return adev_get_active_input(adev);
2501
2502 return NULL;
2503}
2504
Carter Hsu2e429db2019-05-14 18:50:52 +08002505/*
2506 * Aligned with policy.h
2507 */
2508static inline int source_priority(int inputSource)
2509{
2510 switch (inputSource) {
2511 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2512 return 9;
2513 case AUDIO_SOURCE_CAMCORDER:
2514 return 8;
2515 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2516 return 7;
2517 case AUDIO_SOURCE_UNPROCESSED:
2518 return 6;
2519 case AUDIO_SOURCE_MIC:
2520 return 5;
2521 case AUDIO_SOURCE_ECHO_REFERENCE:
2522 return 4;
2523 case AUDIO_SOURCE_FM_TUNER:
2524 return 3;
2525 case AUDIO_SOURCE_VOICE_RECOGNITION:
2526 return 2;
2527 case AUDIO_SOURCE_HOTWORD:
2528 return 1;
2529 default:
2530 break;
2531 }
2532 return 0;
2533}
2534
2535static struct stream_in *get_priority_input(struct audio_device *adev)
2536{
2537 struct listnode *node;
2538 struct audio_usecase *usecase;
2539 int last_priority = 0, priority;
2540 struct stream_in *priority_in = NULL;
2541 struct stream_in *in;
2542
2543 list_for_each(node, &adev->usecase_list) {
2544 usecase = node_to_item(node, struct audio_usecase, list);
2545 if (usecase->type == PCM_CAPTURE) {
2546 in = usecase->stream.in;
2547 if (!in)
2548 continue;
2549 priority = source_priority(in->source);
2550
2551 if (priority > last_priority) {
2552 last_priority = priority;
2553 priority_in = in;
2554 }
2555 }
2556 }
2557 return priority_in;
2558}
2559
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002560int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002562 snd_device_t out_snd_device = SND_DEVICE_NONE;
2563 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002564 struct audio_usecase *usecase = NULL;
2565 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002566 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002567 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302568 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002569 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002570 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302572 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2573
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002574 usecase = get_usecase_from_list(adev, uc_id);
2575 if (usecase == NULL) {
2576 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2577 return -EINVAL;
2578 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002580 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002581 (usecase->type == VOIP_CALL) ||
2582 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302583 if(usecase->stream.out == NULL) {
2584 ALOGE("%s: stream.out is NULL", __func__);
2585 return -EINVAL;
2586 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002587 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002588 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2589 uc_id);
2590 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2591 uc_id);
2592 } else {
2593 out_snd_device = platform_get_output_snd_device(adev->platform,
2594 usecase->stream.out);
2595 in_snd_device = platform_get_input_snd_device(adev->platform,
2596 NULL,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002597 &usecase->stream.out->device_list);
Guodong Hu267bdf82019-08-12 19:22:32 +08002598 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002599 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302600 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302601 if (usecase->stream.inout == NULL) {
2602 ALOGE("%s: stream.inout is NULL", __func__);
2603 return -EINVAL;
2604 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002605 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302606 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2607 stream_out.format = usecase->stream.inout->out_config.format;
2608 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2609 out_snd_device = platform_get_output_snd_device(adev->platform,
2610 &stream_out);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002611 assign_devices(&usecase->device_list,
2612 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302613 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2614 if (usecase->stream.inout == NULL) {
2615 ALOGE("%s: stream.inout is NULL", __func__);
2616 return -EINVAL;
2617 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002618 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, NULL);
2619 assign_devices(&usecase->device_list,
2620 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002621 } else {
2622 /*
2623 * If the voice call is active, use the sound devices of voice call usecase
2624 * so that it would not result any device switch. All the usecases will
2625 * be switched to new device when select_devices() is called for voice call
2626 * usecase. This is to avoid switching devices for voice call when
2627 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002628 * choose voice call device only if the use case device is
2629 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002630 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002631 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002632 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002633 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002634 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2635 is_codec_backend_out_device_type(&usecase->device_list)) ||
2636 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2637 is_codec_backend_in_device_type(&usecase->device_list)) ||
2638 is_single_device_type_equal(&vc_usecase->device_list,
2639 AUDIO_DEVICE_OUT_HEARING_AID) ||
2640 is_single_device_type_equal(&usecase->device_list,
2641 AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002642 in_snd_device = vc_usecase->in_snd_device;
2643 out_snd_device = vc_usecase->out_snd_device;
2644 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002645 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002646 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002647 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002648 if ((voip_usecase != NULL) &&
2649 (usecase->type == PCM_PLAYBACK) &&
2650 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002651 out_snd_device_backend_match = platform_check_backends_match(
2652 voip_usecase->out_snd_device,
2653 platform_get_output_snd_device(
2654 adev->platform,
2655 usecase->stream.out));
2656 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002657 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2658 (is_codec_backend_out_device_type(&usecase->device_list) ||
2659 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002660 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002661 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002662 in_snd_device = voip_usecase->in_snd_device;
2663 out_snd_device = voip_usecase->out_snd_device;
2664 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002665 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002666 hfp_ucid = audio_extn_hfp_get_usecase();
2667 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002668 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002669 in_snd_device = hfp_usecase->in_snd_device;
2670 out_snd_device = hfp_usecase->out_snd_device;
2671 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002672 }
2673 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302674 if (usecase->stream.out == NULL) {
2675 ALOGE("%s: stream.out is NULL", __func__);
2676 return -EINVAL;
2677 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002678 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002679 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002680 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002681 struct stream_out *voip_out = adev->primary_output;
2682 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002683 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002684 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2685 else
2686 out_snd_device = platform_get_output_snd_device(adev->platform,
2687 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002688 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002689
Eric Laurent637e2d42018-11-15 12:24:31 -08002690 if (voip_usecase)
2691 voip_out = voip_usecase->stream.out;
2692
2693 if (usecase->stream.out == voip_out && voip_in != NULL)
2694 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002695 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002696 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302697 if (usecase->stream.in == NULL) {
2698 ALOGE("%s: stream.in is NULL", __func__);
2699 return -EINVAL;
2700 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002701 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002702 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002703 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002704 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002705 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002706 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002707
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002708 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002709 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002710 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2711 USECASE_AUDIO_PLAYBACK_VOIP);
2712
Carter Hsu2e429db2019-05-14 18:50:52 +08002713 usecase->stream.in->enable_ec_port = false;
2714
Eric Laurent637e2d42018-11-15 12:24:31 -08002715 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002716 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002717 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002718 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002719 } else if (adev->primary_output &&
2720 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002721 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002722 } else {
2723 /* forcing speaker o/p device to get matching i/p pair
2724 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002725 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002726 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002727 priority_in = voip_in;
2728 } else {
2729 /* get the input with the highest priority source*/
2730 priority_in = get_priority_input(adev);
2731
2732 if (!priority_in)
2733 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002734 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002735
Eric Laurent637e2d42018-11-15 12:24:31 -08002736 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002737 priority_in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002738 &out_devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002739 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002740 }
2741 }
2742
2743 if (out_snd_device == usecase->out_snd_device &&
2744 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302745
2746 if (!force_device_switch(usecase))
2747 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 }
2749
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002750 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002751 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002752 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002753 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2754 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302755 }
2756
Aalique Grahame22e49102018-12-18 14:23:57 -08002757 if (out_snd_device != SND_DEVICE_NONE &&
2758 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2759 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2760 __func__,
2761 use_case_table[uc_id],
2762 adev->last_logged_snd_device[uc_id][0],
2763 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2764 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2765 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2766 -1,
2767 out_snd_device,
2768 platform_get_snd_device_name(out_snd_device),
2769 platform_get_snd_device_acdb_id(out_snd_device));
2770 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2771 }
2772 if (in_snd_device != SND_DEVICE_NONE &&
2773 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2774 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2775 __func__,
2776 use_case_table[uc_id],
2777 adev->last_logged_snd_device[uc_id][1],
2778 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2779 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2780 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2781 -1,
2782 in_snd_device,
2783 platform_get_snd_device_name(in_snd_device),
2784 platform_get_snd_device_acdb_id(in_snd_device));
2785 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2786 }
2787
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002788
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789 /*
2790 * Limitation: While in call, to do a device switch we need to disable
2791 * and enable both RX and TX devices though one of them is same as current
2792 * device.
2793 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002794 if ((usecase->type == VOICE_CALL) &&
2795 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2796 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002797 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002798 }
2799
2800 if (((usecase->type == VOICE_CALL) ||
2801 (usecase->type == VOIP_CALL)) &&
2802 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2803 /* Disable sidetone only if voice/voip call already exists */
2804 if (voice_is_call_state_active(adev) ||
2805 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002806 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002807
2808 /* Disable aanc only if voice call exists */
2809 if (voice_is_call_state_active(adev))
2810 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002811 }
2812
Aalique Grahame22e49102018-12-18 14:23:57 -08002813 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2814 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002815 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302816 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002817 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2818 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2819 else
2820 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302821 }
2822
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002823 /* Disable current sound devices */
2824 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002825 disable_audio_route(adev, usecase);
2826 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 }
2828
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002829 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002830 disable_audio_route(adev, usecase);
2831 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832 }
2833
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002834 /* Applicable only on the targets that has external modem.
2835 * New device information should be sent to modem before enabling
2836 * the devices to reduce in-call device switch time.
2837 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002838 if ((usecase->type == VOICE_CALL) &&
2839 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2840 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002841 status = platform_switch_voice_call_enable_device_config(adev->platform,
2842 out_snd_device,
2843 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002844 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002845
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002846 /* Enable new sound devices */
2847 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002848 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302849 if (platform_check_codec_asrc_support(adev->platform))
2850 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002851 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852 }
2853
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002854 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302855 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002856 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002857 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002858
Avinash Vaish71a8b972014-07-24 15:36:33 +05302859 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002860 status = platform_switch_voice_call_device_post(adev->platform,
2861 out_snd_device,
2862 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302863 enable_audio_route_for_voice_usecases(adev, usecase);
2864 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002865
sangwoo170731f2013-06-08 15:36:36 +09002866 usecase->in_snd_device = in_snd_device;
2867 usecase->out_snd_device = out_snd_device;
2868
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302869 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2870 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302871 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002872 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002873 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002874 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2875 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2876 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2877 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2878 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2879 /*
2880 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2881 * configured device sample rate, if not update the COPP rate to be equal to the
2882 * device sample rate, else open COPP at stream sample rate
2883 */
2884 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2885 usecase->stream.out->sample_rate,
2886 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302887 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302888 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2889 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302890 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002891 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2892 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2893 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2894 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002895 }
2896 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002897
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002898 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002899
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002900 /* If input stream is already running then effect needs to be
2901 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002902 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002903 check_and_enable_effect(adev);
2904
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002905 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002906 /* Enable aanc only if voice call exists */
2907 if (voice_is_call_state_active(adev))
2908 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2909
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002910 /* Enable sidetone only if other voice/voip call already exists */
2911 if (voice_is_call_state_active(adev) ||
2912 voice_extn_compress_voip_is_started(adev))
2913 voice_set_sidetone(adev, out_snd_device, true);
2914 }
2915
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002916 /* Applicable only on the targets that has external modem.
2917 * Enable device command should be sent to modem only after
2918 * enabling voice call mixer controls
2919 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002920 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002921 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2922 out_snd_device,
2923 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302924
2925 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002926 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302927 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002928 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302929 if (is_bt_soc_on(adev) == false){
2930 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002931 if (in->pcm != NULL)
2932 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302933 }
2934 }
2935 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2936 && usecase->stream.out->started) {
2937 if (is_bt_soc_on(adev) == false) {
2938 ALOGD("BT SCO/A2DP disconnected while in connection");
2939 out_standby_l(&usecase->stream.out->stream.common);
2940 }
2941 }
2942 } else if ((usecase->stream.out != NULL) &&
2943 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302944 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2945 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08002946 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302947 usecase->stream.out->started) {
2948 if (is_bt_soc_on(adev) == false) {
2949 ALOGD("BT SCO/A2dp disconnected while in connection");
2950 out_standby_l(&usecase->stream.out->stream.common);
2951 }
2952 }
2953 }
2954
Yung Ti Su70cb8242018-06-22 17:38:47 +08002955 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002956 struct stream_out *voip_out = voip_usecase->stream.out;
2957 audio_extn_utils_send_app_type_gain(adev,
2958 voip_out->app_type_cfg.app_type,
2959 &voip_out->app_type_cfg.gain[0]);
2960 }
2961
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302962 ALOGD("%s: done",__func__);
2963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964 return status;
2965}
2966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967static int stop_input_stream(struct stream_in *in)
2968{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302969 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302971
2972 if (in == NULL) {
2973 ALOGE("%s: stream_in ptr is NULL", __func__);
2974 return -EINVAL;
2975 }
2976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002978 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979
Eric Laurent994a6932013-07-17 11:51:42 -07002980 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002981 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982 uc_info = get_usecase_from_list(adev, in->usecase);
2983 if (uc_info == NULL) {
2984 ALOGE("%s: Could not find the usecase (%d) in the list",
2985 __func__, in->usecase);
2986 return -EINVAL;
2987 }
2988
Carter Hsu2e429db2019-05-14 18:50:52 +08002989 priority_in = get_priority_input(adev);
2990
Derek Chenea197282019-01-07 17:35:01 -08002991 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2992 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002993
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002994 /* Close in-call recording streams */
2995 voice_check_and_stop_incall_rec_usecase(adev, in);
2996
Eric Laurent150dbfe2013-02-27 14:31:02 -08002997 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002998 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002999
3000 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003001 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003003 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303004 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3005
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003006 list_remove(&uc_info->list);
3007 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008
Carter Hsu2e429db2019-05-14 18:50:52 +08003009 if (priority_in == in) {
3010 priority_in = get_priority_input(adev);
3011 if (priority_in)
3012 select_devices(adev, priority_in->usecase);
3013 }
3014
Vatsal Buchac09ae062018-11-14 13:25:08 +05303015 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003016 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 return ret;
3018}
3019
3020int start_input_stream(struct stream_in *in)
3021{
3022 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003023 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303025
3026 if (in == NULL) {
3027 ALOGE("%s: stream_in ptr is NULL", __func__);
3028 return -EINVAL;
3029 }
3030
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003032 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003033 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034
Mingming Yin2664a5b2015-09-03 10:53:11 -07003035 if (get_usecase_from_list(adev, usecase) == NULL)
3036 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303037 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3038 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003039
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303040 if (CARD_STATUS_OFFLINE == in->card_status||
3041 CARD_STATUS_OFFLINE == adev->card_status) {
3042 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303043 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303044 goto error_config;
3045 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303046
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003047 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303048 if (!adev->bt_sco_on) {
3049 ALOGE("%s: SCO profile is not ready, return error", __func__);
3050 ret = -EIO;
3051 goto error_config;
3052 }
3053 }
3054
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003055 /* Check if source matches incall recording usecase criteria */
3056 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3057 if (ret)
3058 goto error_config;
3059 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003060 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3061
3062 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3063 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3064 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003065 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003066 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003067
Eric Laurentb23d5282013-05-14 15:27:20 -07003068 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 if (in->pcm_device_id < 0) {
3070 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3071 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003072 ret = -EINVAL;
3073 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003077
3078 if (!uc_info) {
3079 ret = -ENOMEM;
3080 goto error_config;
3081 }
3082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083 uc_info->id = in->usecase;
3084 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003085 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003086 list_init(&uc_info->device_list);
3087 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003088 uc_info->in_snd_device = SND_DEVICE_NONE;
3089 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003091 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003092 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303093 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3094 adev->perf_lock_opts,
3095 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003096 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097
Derek Chenea197282019-01-07 17:35:01 -08003098 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3099 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003100
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303101 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3102
Haynes Mathew George16081042017-05-31 17:16:49 -07003103 if (audio_extn_cin_attached_usecase(in->usecase)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303104 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303105 if (ret)
3106 goto error_open;
3107 else
3108 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003109 }
3110
Haynes Mathew George16081042017-05-31 17:16:49 -07003111 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003112 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003113 ALOGE("%s: pcm stream not ready", __func__);
3114 goto error_open;
3115 }
3116 ret = pcm_start(in->pcm);
3117 if (ret < 0) {
3118 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3119 goto error_open;
3120 }
3121 } else {
3122 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3123 unsigned int pcm_open_retry_count = 0;
3124
3125 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
3126 flags |= PCM_MMAP | PCM_NOIRQ;
3127 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3128 } else if (in->realtime) {
3129 flags |= PCM_MMAP | PCM_NOIRQ;
3130 }
3131
Garmond Leunge2433c32017-09-28 21:51:22 -07003132 if (audio_extn_ffv_get_stream() == in) {
3133 ALOGD("%s: ffv stream, update pcm config", __func__);
3134 audio_extn_ffv_update_pcm_config(&config);
3135 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003136 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3137 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3138
3139 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003140 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003141 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003142 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003143 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303144 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303145 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3146 adev->card_status = CARD_STATUS_OFFLINE;
3147 in->card_status = CARD_STATUS_OFFLINE;
3148 ret = -EIO;
3149 goto error_open;
3150 }
3151
Haynes Mathew George16081042017-05-31 17:16:49 -07003152 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3153 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3154 if (in->pcm != NULL) {
3155 pcm_close(in->pcm);
3156 in->pcm = NULL;
3157 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003158 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003159 ret = -EIO;
3160 goto error_open;
3161 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003162 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003163 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3164 continue;
3165 }
3166 break;
3167 }
3168
3169 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003170 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003171 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003172 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003173 if (ret < 0) {
3174 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3175 pcm_close(in->pcm);
3176 in->pcm = NULL;
3177 goto error_open;
3178 }
3179 register_in_stream(in);
3180 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003181 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003182 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003183 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003184 if (ret < 0) {
3185 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003186 pcm_close(in->pcm);
3187 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003188 goto error_open;
3189 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003190 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003191 }
3192
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003193 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003194 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3195 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003196
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003197 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303198 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3199
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303200done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003201 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303202 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003203 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303204 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003205 return ret;
3206
3207error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003208 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303209 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003211
Eric Laurentc8400632013-02-14 19:04:54 -08003212error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303213 /*
3214 * sleep 50ms to allow sufficient time for kernel
3215 * drivers to recover incases like SSR.
3216 */
3217 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003218 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303219 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003220 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221}
3222
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003223void lock_input_stream(struct stream_in *in)
3224{
3225 pthread_mutex_lock(&in->pre_lock);
3226 pthread_mutex_lock(&in->lock);
3227 pthread_mutex_unlock(&in->pre_lock);
3228}
3229
3230void lock_output_stream(struct stream_out *out)
3231{
3232 pthread_mutex_lock(&out->pre_lock);
3233 pthread_mutex_lock(&out->lock);
3234 pthread_mutex_unlock(&out->pre_lock);
3235}
3236
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003237/* must be called with out->lock locked */
3238static int send_offload_cmd_l(struct stream_out* out, int command)
3239{
3240 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3241
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003242 if (!cmd) {
3243 ALOGE("failed to allocate mem for command 0x%x", command);
3244 return -ENOMEM;
3245 }
3246
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003247 ALOGVV("%s %d", __func__, command);
3248
3249 cmd->cmd = command;
3250 list_add_tail(&out->offload_cmd_list, &cmd->node);
3251 pthread_cond_signal(&out->offload_cond);
3252 return 0;
3253}
3254
3255/* must be called iwth out->lock locked */
3256static void stop_compressed_output_l(struct stream_out *out)
3257{
3258 out->offload_state = OFFLOAD_STATE_IDLE;
3259 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003260 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003261 if (out->compr != NULL) {
3262 compress_stop(out->compr);
3263 while (out->offload_thread_blocked) {
3264 pthread_cond_wait(&out->cond, &out->lock);
3265 }
3266 }
3267}
3268
Varun Balaraje49253e2017-07-06 19:48:56 +05303269bool is_interactive_usecase(audio_usecase_t uc_id)
3270{
3271 unsigned int i;
3272 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3273 if (uc_id == interactive_usecases[i])
3274 return true;
3275 }
3276 return false;
3277}
3278
3279static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3280{
3281 audio_usecase_t ret_uc = USECASE_INVALID;
3282 unsigned int intract_uc_index;
3283 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3284
3285 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3286 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3287 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3288 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3289 ret_uc = interactive_usecases[intract_uc_index];
3290 break;
3291 }
3292 }
3293
3294 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3295 return ret_uc;
3296}
3297
3298static void free_interactive_usecase(struct audio_device *adev,
3299 audio_usecase_t uc_id)
3300{
3301 unsigned int interact_uc_index;
3302 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3303
3304 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3305 if (interactive_usecases[interact_uc_index] == uc_id) {
3306 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3307 break;
3308 }
3309 }
3310 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3311}
3312
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003313bool is_offload_usecase(audio_usecase_t uc_id)
3314{
3315 unsigned int i;
3316 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3317 if (uc_id == offload_usecases[i])
3318 return true;
3319 }
3320 return false;
3321}
3322
Dhananjay Kumarac341582017-02-23 23:42:25 +05303323static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003324{
vivek mehta446c3962015-09-14 10:57:35 -07003325 audio_usecase_t ret_uc = USECASE_INVALID;
3326 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003327 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003328 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303329 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003330 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3331 else
3332 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003333
vivek mehta446c3962015-09-14 10:57:35 -07003334 pthread_mutex_lock(&adev->lock);
3335 if (get_usecase_from_list(adev, ret_uc) != NULL)
3336 ret_uc = USECASE_INVALID;
3337 pthread_mutex_unlock(&adev->lock);
3338
3339 return ret_uc;
3340 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003341
3342 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003343 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3344 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3345 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3346 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003347 break;
3348 }
3349 }
vivek mehta446c3962015-09-14 10:57:35 -07003350
3351 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3352 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003353}
3354
3355static void free_offload_usecase(struct audio_device *adev,
3356 audio_usecase_t uc_id)
3357{
vivek mehta446c3962015-09-14 10:57:35 -07003358 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003359 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003360
3361 if (!adev->multi_offload_enable)
3362 return;
3363
3364 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3365 if (offload_usecases[offload_uc_index] == uc_id) {
3366 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003367 break;
3368 }
3369 }
3370 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3371}
3372
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003373static void *offload_thread_loop(void *context)
3374{
3375 struct stream_out *out = (struct stream_out *) context;
3376 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003377 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003378
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003379 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003380 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003381 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3382
3383 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003384 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003385 out->offload_state = OFFLOAD_STATE_IDLE;
3386 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003387 for (;;) {
3388 struct offload_cmd *cmd = NULL;
3389 stream_callback_event_t event;
3390 bool send_callback = false;
3391
3392 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3393 __func__, list_empty(&out->offload_cmd_list),
3394 out->offload_state);
3395 if (list_empty(&out->offload_cmd_list)) {
3396 ALOGV("%s SLEEPING", __func__);
3397 pthread_cond_wait(&out->offload_cond, &out->lock);
3398 ALOGV("%s RUNNING", __func__);
3399 continue;
3400 }
3401
3402 item = list_head(&out->offload_cmd_list);
3403 cmd = node_to_item(item, struct offload_cmd, node);
3404 list_remove(item);
3405
3406 ALOGVV("%s STATE %d CMD %d out->compr %p",
3407 __func__, out->offload_state, cmd->cmd, out->compr);
3408
3409 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3410 free(cmd);
3411 break;
3412 }
3413
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003414 // allow OFFLOAD_CMD_ERROR reporting during standby
3415 // this is needed to handle failures during compress_open
3416 // Note however that on a pause timeout, the stream is closed
3417 // and no offload usecase will be active. Therefore this
3418 // special case is needed for compress_open failures alone
3419 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3420 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003421 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003422 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003423 pthread_cond_signal(&out->cond);
3424 continue;
3425 }
3426 out->offload_thread_blocked = true;
3427 pthread_mutex_unlock(&out->lock);
3428 send_callback = false;
3429 switch(cmd->cmd) {
3430 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003431 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003432 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003433 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003434 send_callback = true;
3435 event = STREAM_CBK_EVENT_WRITE_READY;
3436 break;
3437 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003438 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303439 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003440 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303441 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003442 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303443 if (ret < 0)
3444 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303445 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303446 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003447 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003448 else
3449 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003450 if (-ENETRESET != ret && !(-EINTR == ret &&
3451 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303452 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303453 pthread_mutex_lock(&out->lock);
3454 out->send_new_metadata = 1;
3455 out->send_next_track_params = true;
3456 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303457 event = STREAM_CBK_EVENT_DRAIN_READY;
3458 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3459 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303460 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003461 break;
3462 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003463 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003464 ret = compress_drain(out->compr);
3465 ALOGD("copl(%p):out of compress_drain", out);
3466 // EINTR check avoids drain interruption due to SSR
3467 if (-ENETRESET != ret && !(-EINTR == ret &&
3468 CARD_STATUS_OFFLINE == out->card_status)) {
3469 send_callback = true;
3470 event = STREAM_CBK_EVENT_DRAIN_READY;
3471 } else
3472 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003473 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303474 case OFFLOAD_CMD_ERROR:
3475 ALOGD("copl(%p): sending error callback to AF", out);
3476 send_callback = true;
3477 event = STREAM_CBK_EVENT_ERROR;
3478 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003479 default:
3480 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3481 break;
3482 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003483 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003484 out->offload_thread_blocked = false;
3485 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003486 if (send_callback && out->client_callback) {
3487 ALOGVV("%s: sending client_callback event %d", __func__, event);
3488 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003489 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490 free(cmd);
3491 }
3492
3493 pthread_cond_signal(&out->cond);
3494 while (!list_empty(&out->offload_cmd_list)) {
3495 item = list_head(&out->offload_cmd_list);
3496 list_remove(item);
3497 free(node_to_item(item, struct offload_cmd, node));
3498 }
3499 pthread_mutex_unlock(&out->lock);
3500
3501 return NULL;
3502}
3503
3504static int create_offload_callback_thread(struct stream_out *out)
3505{
3506 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3507 list_init(&out->offload_cmd_list);
3508 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3509 offload_thread_loop, out);
3510 return 0;
3511}
3512
3513static int destroy_offload_callback_thread(struct stream_out *out)
3514{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003515 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003516 stop_compressed_output_l(out);
3517 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3518
3519 pthread_mutex_unlock(&out->lock);
3520 pthread_join(out->offload_thread, (void **) NULL);
3521 pthread_cond_destroy(&out->offload_cond);
3522
3523 return 0;
3524}
3525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526static int stop_output_stream(struct stream_out *out)
3527{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303528 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529 struct audio_usecase *uc_info;
3530 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003531 bool has_voip_usecase =
3532 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533
Eric Laurent994a6932013-07-17 11:51:42 -07003534 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003535 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536 uc_info = get_usecase_from_list(adev, out->usecase);
3537 if (uc_info == NULL) {
3538 ALOGE("%s: Could not find the usecase (%d) in the list",
3539 __func__, out->usecase);
3540 return -EINVAL;
3541 }
3542
Derek Chenea197282019-01-07 17:35:01 -08003543 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3544 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003545
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003546 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303547 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003548 if (adev->visualizer_stop_output != NULL)
3549 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003550
3551 audio_extn_dts_remove_state_notifier_node(out->usecase);
3552
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003553 if (adev->offload_effects_stop_output != NULL)
3554 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003555 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3556 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3557 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003558 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003559
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003560 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3561 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003562 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003563 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003564
Eric Laurent150dbfe2013-02-27 14:31:02 -08003565 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003566 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003567
3568 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003569 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570
Aalique Grahame22e49102018-12-18 14:23:57 -08003571 audio_extn_extspk_update(adev->extspk);
3572
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003573 if (is_offload_usecase(out->usecase)) {
3574 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3575 adev->dsp_bit_width_enforce_mode,
3576 false);
3577 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003578 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003579 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3580 false);
3581
3582 if (ret != 0)
3583 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3584 /* default service interval was successfully updated,
3585 reopen USB backend with new service interval */
3586 ret = 0;
3587 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003588
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003589 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303590 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003591 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303592 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003593 ALOGV("Disable passthrough , reset mixer to pcm");
3594 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003595#ifdef AUDIO_GKI_ENABLED
3596 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3597 out->compr_config.codec->reserved[0] = 0;
3598#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003599 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003600#endif
Mingming Yin21854652016-04-13 11:54:02 -07003601 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003602 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3603 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003604
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303605 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003606 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303607 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303608
Manish Dewangan21a850a2017-08-14 12:03:55 +05303609 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003610 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3611 if (ret < 0)
3612 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3613 }
3614
juyuchen2d415992018-11-16 14:15:16 +08003615 /* 1) media + voip output routing to handset must route media back to
3616 speaker when voip stops.
3617 2) trigger voip input to reroute when voip output changes to
3618 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003619 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003620 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003621 struct listnode *node;
3622 struct audio_usecase *usecase;
3623 list_for_each(node, &adev->usecase_list) {
3624 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003625 if ((usecase->type == PCM_CAPTURE &&
3626 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3627 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003628 continue;
3629
3630 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3631 __func__, usecase->id, use_case_table[usecase->id],
3632 out->usecase, use_case_table[out->usecase]);
3633 select_devices(adev, usecase->id);
3634 }
3635 }
3636
Garmond Leung5fd0b552018-04-17 11:56:12 -07003637 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003638 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639 return ret;
3640}
3641
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003642struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3643 unsigned int flags, unsigned int pcm_open_retry_count,
3644 struct pcm_config *config)
3645{
3646 struct pcm* pcm = NULL;
3647
3648 while (1) {
3649 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3650 if (pcm == NULL || !pcm_is_ready(pcm)) {
3651 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3652 if (pcm != NULL) {
3653 pcm_close(pcm);
3654 pcm = NULL;
3655 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003656 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003657 return NULL;
3658
Weiyin Jiang72197252019-10-09 11:49:32 +08003659 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003660 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3661 continue;
3662 }
3663 break;
3664 }
3665
3666 if (pcm_is_ready(pcm)) {
3667 int ret = pcm_prepare(pcm);
3668 if (ret < 0) {
3669 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3670 pcm_close(pcm);
3671 pcm = NULL;
3672 }
3673 }
3674
3675 return pcm;
3676}
3677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678int start_output_stream(struct stream_out *out)
3679{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681 struct audio_usecase *uc_info;
3682 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003683 char mixer_ctl_name[128];
3684 struct mixer_ctl *ctl = NULL;
3685 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303686 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003687 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688
Haynes Mathew George380745d2017-10-04 15:27:45 -07003689 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003690 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3691 ret = -EINVAL;
3692 goto error_config;
3693 }
3694
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003695 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303696 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003697 get_device_types(&out->device_list), is_haptic_usecase);
3698
3699 bool is_speaker_active = compare_device_type(&out->device_list,
3700 AUDIO_DEVICE_OUT_SPEAKER);
3701 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3702 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303703
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303704 if (CARD_STATUS_OFFLINE == out->card_status ||
3705 CARD_STATUS_OFFLINE == adev->card_status) {
3706 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303707 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303708 goto error_config;
3709 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303710
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003711 //Update incall music usecase to reflect correct voice session
3712 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3713 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3714 if (ret != 0) {
3715 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3716 __func__, ret);
3717 goto error_config;
3718 }
3719 }
3720
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003721 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003722 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003723 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303724 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303725 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303726 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3727 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3728 ret = -EAGAIN;
3729 goto error_config;
3730 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303731 }
3732 }
3733 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003734 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303735 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003736 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303737 //combo usecase just by pass a2dp
3738 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003739 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303740 } else {
3741 ALOGE("%s: SCO profile is not ready, return error", __func__);
3742 ret = -EAGAIN;
3743 goto error_config;
3744 }
3745 }
3746 }
3747
Eric Laurentb23d5282013-05-14 15:27:20 -07003748 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 if (out->pcm_device_id < 0) {
3750 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3751 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003752 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003753 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754 }
3755
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003756 if (is_haptic_usecase) {
3757 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3758 if (adev->haptic_pcm_device_id < 0) {
3759 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3760 __func__, adev->haptic_pcm_device_id, out->usecase);
3761 ret = -EINVAL;
3762 goto error_config;
3763 }
3764 }
3765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003767
3768 if (!uc_info) {
3769 ret = -ENOMEM;
3770 goto error_config;
3771 }
3772
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773 uc_info->id = out->usecase;
3774 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003775 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003776 list_init(&uc_info->device_list);
3777 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003778 uc_info->in_snd_device = SND_DEVICE_NONE;
3779 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003780
3781 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003782 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003783 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3784 /* USB backend is not reopened immediately.
3785 This is eventually done as part of select_devices */
3786 }
3787
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003788 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003789
Wei Wangf7ca6c92017-11-21 14:51:20 -08003790 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303791 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3792 adev->perf_lock_opts,
3793 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303794
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003795 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303796 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303797 if (audio_extn_passthru_is_enabled() &&
3798 audio_extn_passthru_is_passthrough_stream(out)) {
3799 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303800 }
3801 }
3802
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003803 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003804 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303805 if (!a2dp_combo) {
3806 check_a2dp_restore_l(adev, out, false);
3807 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003808 struct listnode dev;
3809 list_init(&dev);
3810 assign_devices(&dev, &out->device_list);
3811 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3812 reassign_device_list(&out->device_list,
3813 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003814 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003815 reassign_device_list(&out->device_list,
3816 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303817 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003818 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303819 }
3820 } else {
3821 select_devices(adev, out->usecase);
3822 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003823
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003824 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3825 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003826 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003827 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003828
Derek Chenea197282019-01-07 17:35:01 -08003829 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3830 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003831
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003832 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3833 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003834
3835 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003836 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003837 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3838 ALOGE("%s: pcm stream not ready", __func__);
3839 goto error_open;
3840 }
3841 ret = pcm_start(out->pcm);
3842 if (ret < 0) {
3843 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3844 goto error_open;
3845 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003846 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003847 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003848 unsigned int flags = PCM_OUT;
3849 unsigned int pcm_open_retry_count = 0;
3850 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3851 flags |= PCM_MMAP | PCM_NOIRQ;
3852 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003853 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003854 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003855 } else
3856 flags |= PCM_MONOTONIC;
3857
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003858 if ((adev->vr_audio_mode_enabled) &&
3859 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3860 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3861 "PCM_Dev %d Topology", out->pcm_device_id);
3862 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3863 if (!ctl) {
3864 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3865 __func__, mixer_ctl_name);
3866 } else {
3867 //if success use ULLPP
3868 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3869 __func__, mixer_ctl_name, out->pcm_device_id);
3870 //There is a still a possibility that some sessions
3871 // that request for FAST|RAW when 3D audio is active
3872 //can go through ULLPP. Ideally we expects apps to
3873 //listen to audio focus and stop concurrent playback
3874 //Also, we will look for mode flag (voice_in_communication)
3875 //before enabling the realtime flag.
3876 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3877 }
3878 }
3879
Surendar Karka91fa3682018-07-02 18:12:12 +05303880 if (out->realtime)
3881 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3882 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3883
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003884 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3885 flags, pcm_open_retry_count,
3886 &(out->config));
3887 if (out->pcm == NULL) {
3888 ret = -EIO;
3889 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003890 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003891
3892 if (is_haptic_usecase) {
3893 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3894 adev->haptic_pcm_device_id,
3895 flags, pcm_open_retry_count,
3896 &(adev->haptics_config));
3897 // failure to open haptics pcm shouldnt stop audio,
3898 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003899
3900 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3901 ALOGD("%s: enable haptic audio synchronization", __func__);
3902 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3903 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003904 }
3905
Surendar Karka91fa3682018-07-02 18:12:12 +05303906 if (!out->realtime)
3907 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303908 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003909
Zhou Song2b8f28f2017-09-11 10:51:38 +08003910 // apply volume for voip playback after path is set up
3911 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3912 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303913 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3914 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303915 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3916 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003917 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3918 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303919 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003920 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003921 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303922 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003923 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3924 adev->dsp_bit_width_enforce_mode,
3925 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003926 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003927 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003928 out->compr = compress_open(adev->snd_card,
3929 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003930 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003931 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303932 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303933 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3934 adev->card_status = CARD_STATUS_OFFLINE;
3935 out->card_status = CARD_STATUS_OFFLINE;
3936 ret = -EIO;
3937 goto error_open;
3938 }
3939
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003940 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003941 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003942 compress_close(out->compr);
3943 out->compr = NULL;
3944 ret = -EIO;
3945 goto error_open;
3946 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303947 /* compress_open sends params of the track, so reset the flag here */
3948 out->is_compr_metadata_avail = false;
3949
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003950 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003951 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003952
Fred Oh3f43e742015-03-04 18:42:34 -08003953 /* Since small bufs uses blocking writes, a write will be blocked
3954 for the default max poll time (20s) in the event of an SSR.
3955 Reduce the poll time to observe and deal with SSR faster.
3956 */
Ashish Jain5106d362016-05-11 19:23:33 +05303957 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003958 compress_set_max_poll_wait(out->compr, 1000);
3959 }
3960
Manish Dewangan69426c82017-01-30 17:35:36 +05303961 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303962 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303963
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003964 audio_extn_dts_create_state_notifier_node(out->usecase);
3965 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3966 popcount(out->channel_mask),
3967 out->playback_started);
3968
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003969#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303970 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003971 audio_extn_dolby_send_ddp_endp_params(adev);
3972#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303973 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3974 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003975 if (adev->visualizer_start_output != NULL)
3976 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3977 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303978 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003979 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003980 }
Derek Chenf13dd492018-11-13 14:53:51 -08003981
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003982 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08003983 /* Update cached volume from media to offload/direct stream */
3984 struct listnode *node = NULL;
3985 list_for_each(node, &adev->active_outputs_list) {
3986 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3987 streams_output_ctxt_t,
3988 list);
3989 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3990 out->volume_l = out_ctxt->output->volume_l;
3991 out->volume_r = out_ctxt->output->volume_r;
3992 }
3993 }
3994 out_set_compr_volume(&out->stream,
3995 out->volume_l, out->volume_r);
3996 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003997 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003998
3999 if (ret == 0) {
4000 register_out_stream(out);
4001 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004002 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4003 ALOGE("%s: pcm stream not ready", __func__);
4004 goto error_open;
4005 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004006 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004007 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004008 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004009 if (ret < 0)
4010 goto error_open;
4011 }
4012 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004013 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304014 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004015 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004016
vivek mehtad15d2bf2019-05-17 13:35:10 -07004017 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4018 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4019 audio_low_latency_hint_start();
4020 }
4021
Manish Dewangan21a850a2017-08-14 12:03:55 +05304022 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004023 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004024 if (ret < 0)
4025 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4026 }
4027
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004028 // consider a scenario where on pause lower layers are tear down.
4029 // so on resume, swap mixer control need to be sent only when
4030 // backend is active, hence rather than sending from enable device
4031 // sending it from start of streamtream
4032
4033 platform_set_swap_channels(adev, true);
4034
Haynes Mathew George380745d2017-10-04 15:27:45 -07004035 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304036 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004037 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004038error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004039 if (adev->haptic_pcm) {
4040 pcm_close(adev->haptic_pcm);
4041 adev->haptic_pcm = NULL;
4042 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004043 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304044 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004045 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004046error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304047 /*
4048 * sleep 50ms to allow sufficient time for kernel
4049 * drivers to recover incases like SSR.
4050 */
4051 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004052 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304053 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004054 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055}
4056
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004057static int check_input_parameters(uint32_t sample_rate,
4058 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004059 int channel_count,
4060 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004062 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004063
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304064 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4065 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4066 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004067 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004068 !audio_extn_compr_cap_format_supported(format) &&
4069 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004070 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004071
Aalique Grahame22e49102018-12-18 14:23:57 -08004072 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4073 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4074 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4075 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4076 return -EINVAL;
4077 }
4078
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004079 switch (channel_count) {
4080 case 1:
4081 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304082 case 3:
4083 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004084 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004085 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304086 case 10:
4087 case 12:
4088 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004089 break;
4090 default:
4091 ret = -EINVAL;
4092 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093
4094 switch (sample_rate) {
4095 case 8000:
4096 case 11025:
4097 case 12000:
4098 case 16000:
4099 case 22050:
4100 case 24000:
4101 case 32000:
4102 case 44100:
4103 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004104 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304105 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004106 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304107 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108 break;
4109 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004110 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111 }
4112
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004113 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114}
4115
Naresh Tanniru04f71882018-06-26 17:46:22 +05304116
4117/** Add a value in a list if not already present.
4118 * @return true if value was successfully inserted or already present,
4119 * false if the list is full and does not contain the value.
4120 */
4121static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4122 for (size_t i = 0; i < list_length; i++) {
4123 if (list[i] == value) return true; // value is already present
4124 if (list[i] == 0) { // no values in this slot
4125 list[i] = value;
4126 return true; // value inserted
4127 }
4128 }
4129 return false; // could not insert value
4130}
4131
4132/** Add channel_mask in supported_channel_masks if not already present.
4133 * @return true if channel_mask was successfully inserted or already present,
4134 * false if supported_channel_masks is full and does not contain channel_mask.
4135 */
4136static void register_channel_mask(audio_channel_mask_t channel_mask,
4137 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4138 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4139 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4140}
4141
4142/** Add format in supported_formats if not already present.
4143 * @return true if format was successfully inserted or already present,
4144 * false if supported_formats is full and does not contain format.
4145 */
4146static void register_format(audio_format_t format,
4147 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4148 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4149 "%s: stream can not declare supporting its format %x", __func__, format);
4150}
4151/** Add sample_rate in supported_sample_rates if not already present.
4152 * @return true if sample_rate was successfully inserted or already present,
4153 * false if supported_sample_rates is full and does not contain sample_rate.
4154 */
4155static void register_sample_rate(uint32_t sample_rate,
4156 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4157 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4158 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4159}
4160
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004161static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4162{
4163 uint32_t high = num1, low = num2, temp = 0;
4164
4165 if (!num1 || !num2)
4166 return 0;
4167
4168 if (num1 < num2) {
4169 high = num2;
4170 low = num1;
4171 }
4172
4173 while (low != 0) {
4174 temp = low;
4175 low = high % low;
4176 high = temp;
4177 }
4178 return (num1 * num2)/high;
4179}
4180
4181static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4182{
4183 uint32_t remainder = 0;
4184
4185 if (!multiplier)
4186 return num;
4187
4188 remainder = num % multiplier;
4189 if (remainder)
4190 num += (multiplier - remainder);
4191
4192 return num;
4193}
4194
Aalique Grahame22e49102018-12-18 14:23:57 -08004195static size_t get_stream_buffer_size(size_t duration_ms,
4196 uint32_t sample_rate,
4197 audio_format_t format,
4198 int channel_count,
4199 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004200{
4201 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004202 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004203
Aalique Grahame22e49102018-12-18 14:23:57 -08004204 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004205 if (is_low_latency)
4206 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304207
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004208 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004209 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210
Ralf Herzbd08d632018-09-28 15:50:49 +02004211 /* make sure the size is multiple of 32 bytes and additionally multiple of
4212 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004213 * At 48 kHz mono 16-bit PCM:
4214 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4215 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004216 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004217 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004218 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004219
4220 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004221}
4222
Aalique Grahame22e49102018-12-18 14:23:57 -08004223static size_t get_input_buffer_size(uint32_t sample_rate,
4224 audio_format_t format,
4225 int channel_count,
4226 bool is_low_latency)
4227{
4228 /* Don't know if USB HIFI in this context so use true to be conservative */
4229 if (check_input_parameters(sample_rate, format, channel_count,
4230 true /*is_usb_hifi */) != 0)
4231 return 0;
4232
4233 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4234 sample_rate,
4235 format,
4236 channel_count,
4237 is_low_latency);
4238}
4239
Derek Chenf6318be2017-06-12 17:16:24 -04004240size_t get_output_period_size(uint32_t sample_rate,
4241 audio_format_t format,
4242 int channel_count,
4243 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304244{
4245 size_t size = 0;
4246 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4247
4248 if ((duration == 0) || (sample_rate == 0) ||
4249 (bytes_per_sample == 0) || (channel_count == 0)) {
4250 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4251 bytes_per_sample, channel_count);
4252 return -EINVAL;
4253 }
4254
4255 size = (sample_rate *
4256 duration *
4257 bytes_per_sample *
4258 channel_count) / 1000;
4259 /*
4260 * To have same PCM samples for all channels, the buffer size requires to
4261 * be multiple of (number of channels * bytes per sample)
4262 * For writes to succeed, the buffer must be written at address which is multiple of 32
4263 */
4264 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4265
4266 return (size/(channel_count * bytes_per_sample));
4267}
4268
Zhou Song48453a02018-01-10 17:50:59 +08004269static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304270{
4271 uint64_t actual_frames_rendered = 0;
4272 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4273
4274 /* This adjustment accounts for buffering after app processor.
4275 * It is based on estimated DSP latency per use case, rather than exact.
4276 */
4277 int64_t platform_latency = platform_render_latency(out->usecase) *
4278 out->sample_rate / 1000000LL;
4279
Zhou Song48453a02018-01-10 17:50:59 +08004280 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304281 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4282 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4283 * hence only estimate.
4284 */
George Gao62ebc722019-07-29 16:29:44 -07004285 uint64_t signed_frames = 0;
4286 if (out->written >= kernel_buffer_size)
4287 signed_frames = out->written - kernel_buffer_size;
Ashish Jain5106d362016-05-11 19:23:33 +05304288
George Gao62ebc722019-07-29 16:29:44 -07004289 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask));
4290 if (signed_frames >= platform_latency)
4291 signed_frames = signed_frames - platform_latency;
Ashish Jain5106d362016-05-11 19:23:33 +05304292
Zhou Song48453a02018-01-10 17:50:59 +08004293 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304294 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004295 if (timestamp != NULL )
4296 *timestamp = out->writeAt;
4297 } else if (timestamp != NULL) {
4298 clock_gettime(CLOCK_MONOTONIC, timestamp);
4299 }
4300 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304301
4302 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
George Gao62ebc722019-07-29 16:29:44 -07004303 "bytes/sample %zu channel count %d", __func__, signed_frames,
Ashish Jain5106d362016-05-11 19:23:33 +05304304 (long long int)out->written, (int)kernel_buffer_size,
4305 audio_bytes_per_sample(out->compr_config.codec->format),
4306 popcount(out->channel_mask));
4307
4308 return actual_frames_rendered;
4309}
4310
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4312{
4313 struct stream_out *out = (struct stream_out *)stream;
4314
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004315 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316}
4317
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004318static int out_set_sample_rate(struct audio_stream *stream __unused,
4319 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320{
4321 return -ENOSYS;
4322}
4323
4324static size_t out_get_buffer_size(const struct audio_stream *stream)
4325{
4326 struct stream_out *out = (struct stream_out *)stream;
4327
Varun Balaraje49253e2017-07-06 19:48:56 +05304328 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304329 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304330 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304331 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4332 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4333 else
4334 return out->compr_config.fragment_size;
4335 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004336 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304337 else if (is_offload_usecase(out->usecase) &&
4338 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304339 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004340
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004341 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004342 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004343}
4344
4345static uint32_t out_get_channels(const struct audio_stream *stream)
4346{
4347 struct stream_out *out = (struct stream_out *)stream;
4348
4349 return out->channel_mask;
4350}
4351
4352static audio_format_t out_get_format(const struct audio_stream *stream)
4353{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004354 struct stream_out *out = (struct stream_out *)stream;
4355
4356 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004357}
4358
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004359static int out_set_format(struct audio_stream *stream __unused,
4360 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361{
4362 return -ENOSYS;
4363}
4364
4365static int out_standby(struct audio_stream *stream)
4366{
4367 struct stream_out *out = (struct stream_out *)stream;
4368 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004369 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004370
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304371 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4372 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004374 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004376 if (adev->adm_deregister_stream)
4377 adev->adm_deregister_stream(adev->adm_data, out->handle);
4378
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004379 if (is_offload_usecase(out->usecase))
4380 stop_compressed_output_l(out);
4381
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004382 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004384 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4385 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304386 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004387 pthread_mutex_unlock(&adev->lock);
4388 pthread_mutex_unlock(&out->lock);
4389 ALOGD("VOIP output entered standby");
4390 return 0;
4391 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004392 if (out->pcm) {
4393 pcm_close(out->pcm);
4394 out->pcm = NULL;
4395 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004396 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4397 do_stop = out->playback_started;
4398 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004399
4400 if (out->mmap_shared_memory_fd >= 0) {
4401 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4402 __func__, out->mmap_shared_memory_fd);
4403 close(out->mmap_shared_memory_fd);
4404 out->mmap_shared_memory_fd = -1;
4405 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004406 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004407 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004408 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304409 out->send_next_track_params = false;
4410 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004411 out->gapless_mdata.encoder_delay = 0;
4412 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004413 if (out->compr != NULL) {
4414 compress_close(out->compr);
4415 out->compr = NULL;
4416 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004417 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004418 if (do_stop) {
4419 stop_output_stream(out);
4420 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304421 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004422 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004423 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004424 }
4425 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304426 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004427 return 0;
4428}
4429
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304430static int out_on_error(struct audio_stream *stream)
4431{
4432 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004433 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304434
4435 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004436 // always send CMD_ERROR for offload streams, this
4437 // is needed e.g. when SSR happens within compress_open
4438 // since the stream is active, offload_callback_thread is also active.
4439 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4440 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004441 }
4442 pthread_mutex_unlock(&out->lock);
4443
4444 status = out_standby(&out->stream.common);
4445
4446 lock_output_stream(out);
4447 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004448 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304449 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304450
4451 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4452 ALOGD("Setting previous card status if offline");
4453 out->prev_card_status_offline = true;
4454 }
4455
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304456 pthread_mutex_unlock(&out->lock);
4457
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004458 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304459}
4460
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304461/*
4462 *standby implementation without locks, assumes that the callee already
4463 *has taken adev and out lock.
4464 */
4465int out_standby_l(struct audio_stream *stream)
4466{
4467 struct stream_out *out = (struct stream_out *)stream;
4468 struct audio_device *adev = out->dev;
4469
4470 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4471 stream, out->usecase, use_case_table[out->usecase]);
4472
4473 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004474 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304475 if (adev->adm_deregister_stream)
4476 adev->adm_deregister_stream(adev->adm_data, out->handle);
4477
4478 if (is_offload_usecase(out->usecase))
4479 stop_compressed_output_l(out);
4480
4481 out->standby = true;
4482 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4483 voice_extn_compress_voip_close_output_stream(stream);
4484 out->started = 0;
4485 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004486 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304487 return 0;
4488 } else if (!is_offload_usecase(out->usecase)) {
4489 if (out->pcm) {
4490 pcm_close(out->pcm);
4491 out->pcm = NULL;
4492 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004493 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4494 if (adev->haptic_pcm) {
4495 pcm_close(adev->haptic_pcm);
4496 adev->haptic_pcm = NULL;
4497 }
4498
4499 if (adev->haptic_buffer != NULL) {
4500 free(adev->haptic_buffer);
4501 adev->haptic_buffer = NULL;
4502 adev->haptic_buffer_size = 0;
4503 }
4504 adev->haptic_pcm_device_id = 0;
4505 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304506 } else {
4507 ALOGD("copl(%p):standby", out);
4508 out->send_next_track_params = false;
4509 out->is_compr_metadata_avail = false;
4510 out->gapless_mdata.encoder_delay = 0;
4511 out->gapless_mdata.encoder_padding = 0;
4512 if (out->compr != NULL) {
4513 compress_close(out->compr);
4514 out->compr = NULL;
4515 }
4516 }
4517 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004518 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304519 }
4520 ALOGD("%s: exit", __func__);
4521 return 0;
4522}
4523
Aalique Grahame22e49102018-12-18 14:23:57 -08004524static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004525{
Aalique Grahame22e49102018-12-18 14:23:57 -08004526 struct stream_out *out = (struct stream_out *)stream;
4527
4528 // We try to get the lock for consistency,
4529 // but it isn't necessary for these variables.
4530 // If we're not in standby, we may be blocked on a write.
4531 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4532 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4533 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4534
4535 if (locked) {
4536 pthread_mutex_unlock(&out->lock);
4537 }
4538
4539 // dump error info
4540 (void)error_log_dump(
4541 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004543 return 0;
4544}
4545
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004546static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4547{
4548 int ret = 0;
4549 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004550
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004551 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004552 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004553 return -EINVAL;
4554 }
4555
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304556 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004557
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004558 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4559 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304560 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004561 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004562 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4563 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304564 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004565 }
4566
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004567 ALOGV("%s new encoder delay %u and padding %u", __func__,
4568 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4569
4570 return 0;
4571}
4572
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004573static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4574{
4575 return out == adev->primary_output || out == adev->voice_tx_output;
4576}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004577
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304578// note: this call is safe only if the stream_cb is
4579// removed first in close_output_stream (as is done now).
4580static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4581{
4582 if (!stream || !parms)
4583 return;
4584
4585 struct stream_out *out = (struct stream_out *)stream;
4586 struct audio_device *adev = out->dev;
4587
4588 card_status_t status;
4589 int card;
4590 if (parse_snd_card_status(parms, &card, &status) < 0)
4591 return;
4592
4593 pthread_mutex_lock(&adev->lock);
4594 bool valid_cb = (card == adev->snd_card);
4595 pthread_mutex_unlock(&adev->lock);
4596
4597 if (!valid_cb)
4598 return;
4599
4600 lock_output_stream(out);
4601 if (out->card_status != status)
4602 out->card_status = status;
4603 pthread_mutex_unlock(&out->lock);
4604
4605 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4606 use_case_table[out->usecase],
4607 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4608
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304609 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304610 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304611 if (voice_is_call_state_active(adev) &&
4612 out == adev->primary_output) {
4613 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4614 pthread_mutex_lock(&adev->lock);
4615 voice_stop_call(adev);
4616 adev->mode = AUDIO_MODE_NORMAL;
4617 pthread_mutex_unlock(&adev->lock);
4618 }
4619 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304620 return;
4621}
4622
Kevin Rocardfce19002017-08-07 19:21:36 -07004623static int get_alive_usb_card(struct str_parms* parms) {
4624 int card;
4625 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4626 !audio_extn_usb_alive(card)) {
4627 return card;
4628 }
4629 return -ENODEV;
4630}
4631
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004632int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004633 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004634{
4635 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004636 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004637 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004638 bool bypass_a2dp = false;
4639 bool reconfig = false;
4640 unsigned long service_interval = 0;
4641
4642 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004643 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4644
4645 list_init(&new_devices);
4646 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004647
4648 lock_output_stream(out);
4649 pthread_mutex_lock(&adev->lock);
4650
4651 /*
4652 * When HDMI cable is unplugged the music playback is paused and
4653 * the policy manager sends routing=0. But the audioflinger continues
4654 * to write data until standby time (3sec). As the HDMI core is
4655 * turned off, the write gets blocked.
4656 * Avoid this by routing audio to speaker until standby.
4657 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004658 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4659 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004660 !audio_extn_passthru_is_passthrough_stream(out) &&
4661 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004662 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004663 }
4664 /*
4665 * When A2DP is disconnected the
4666 * music playback is paused and the policy manager sends routing=0
4667 * But the audioflinger continues to write data until standby time
4668 * (3sec). As BT is turned off, the write gets blocked.
4669 * Avoid this by routing audio to speaker until standby.
4670 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004671 if (is_a2dp_out_device_type(&out->device_list) &&
4672 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004673 !audio_extn_a2dp_source_is_ready() &&
4674 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004675 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004676 }
4677 /*
4678 * When USB headset is disconnected the music platback paused
4679 * and the policy manager send routing=0. But if the USB is connected
4680 * back before the standby time, AFE is not closed and opened
4681 * when USB is connected back. So routing to speker will guarantee
4682 * AFE reconfiguration and AFE will be opend once USB is connected again
4683 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004684 if (is_usb_out_device_type(&out->device_list) &&
4685 list_empty(&new_devices) &&
4686 !audio_extn_usb_connected(NULL)) {
4687 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4688 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004689 /* To avoid a2dp to sco overlapping / BT device improper state
4690 * check with BT lib about a2dp streaming support before routing
4691 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004692 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004693 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004694 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4695 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004696 //combo usecase just by pass a2dp
4697 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4698 bypass_a2dp = true;
4699 } else {
4700 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4701 /* update device to a2dp and don't route as BT returned error
4702 * However it is still possible a2dp routing called because
4703 * of current active device disconnection (like wired headset)
4704 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004705 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004706 pthread_mutex_unlock(&adev->lock);
4707 pthread_mutex_unlock(&out->lock);
4708 goto error;
4709 }
4710 }
4711 }
4712
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004713 // Workaround: If routing to an non existing usb device, fail gracefully
4714 // The routing request will otherwise block during 10 second
4715 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004716 if (is_usb_out_device_type(&new_devices)) {
4717 struct str_parms *parms =
4718 str_parms_create_str(get_usb_device_address(&new_devices));
4719 if (!parms)
4720 goto error;
4721 if ((card = get_alive_usb_card(parms)) >= 0) {
4722 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4723 pthread_mutex_unlock(&adev->lock);
4724 pthread_mutex_unlock(&out->lock);
4725 str_parms_destroy(parms);
4726 ret = -ENOSYS;
4727 goto error;
4728 }
4729 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004730 }
4731
4732 /*
4733 * select_devices() call below switches all the usecases on the same
4734 * backend to the new device. Refer to check_usecases_codec_backend() in
4735 * the select_devices(). But how do we undo this?
4736 *
4737 * For example, music playback is active on headset (deep-buffer usecase)
4738 * and if we go to ringtones and select a ringtone, low-latency usecase
4739 * will be started on headset+speaker. As we can't enable headset+speaker
4740 * and headset devices at the same time, select_devices() switches the music
4741 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4742 * So when the ringtone playback is completed, how do we undo the same?
4743 *
4744 * We are relying on the out_set_parameters() call on deep-buffer output,
4745 * once the ringtone playback is ended.
4746 * NOTE: We should not check if the current devices are same as new devices.
4747 * Because select_devices() must be called to switch back the music
4748 * playback to headset.
4749 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004750 if (!list_empty(&new_devices)) {
4751 bool same_dev = compare_devices(&out->device_list, &new_devices);
4752 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004753
4754 if (output_drives_call(adev, out)) {
4755 if (!voice_is_call_state_active(adev)) {
4756 if (adev->mode == AUDIO_MODE_IN_CALL) {
4757 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004758 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004759 service_interval =
4760 audio_extn_usb_find_service_interval(true, true /*playback*/);
4761 audio_extn_usb_set_service_interval(true /*playback*/,
4762 service_interval,
4763 &reconfig);
4764 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4765 }
4766 ret = voice_start_call(adev);
4767 }
4768 } else {
4769 adev->current_call_output = out;
4770 voice_update_devices_for_all_voice_usecases(adev);
4771 }
4772 }
4773
4774 if (!out->standby) {
4775 if (!same_dev) {
4776 ALOGV("update routing change");
4777 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4778 adev->perf_lock_opts,
4779 adev->perf_lock_opts_size);
4780 if (adev->adm_on_routing_change)
4781 adev->adm_on_routing_change(adev->adm_data,
4782 out->handle);
4783 }
4784 if (!bypass_a2dp) {
4785 select_devices(adev, out->usecase);
4786 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004787 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4788 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004789 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004790 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004791 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004792 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004793 }
4794
4795 if (!same_dev) {
4796 // on device switch force swap, lower functions will make sure
4797 // to check if swap is allowed or not.
4798 platform_set_swap_channels(adev, true);
4799 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4800 }
4801 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4802 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004803 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004804 pthread_mutex_lock(&out->compr_mute_lock);
4805 out->a2dp_compress_mute = false;
4806 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4807 pthread_mutex_unlock(&out->compr_mute_lock);
4808 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4809 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4810 }
4811 }
4812 }
4813
4814 pthread_mutex_unlock(&adev->lock);
4815 pthread_mutex_unlock(&out->lock);
4816
4817 /*handles device and call state changes*/
4818 audio_extn_extspk_update(adev->extspk);
4819
4820error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004821 ALOGV("%s: exit: code(%d)", __func__, ret);
4822 return ret;
4823}
4824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004825static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4826{
4827 struct stream_out *out = (struct stream_out *)stream;
4828 struct audio_device *adev = out->dev;
4829 struct str_parms *parms;
4830 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004831 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004832 int ext_controller = -1;
4833 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834
sangwoobc677242013-08-08 16:53:43 +09004835 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004836 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004837 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304838 if (!parms)
4839 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004840
4841 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4842 &ext_stream);
4843 if (err >= 0) {
4844 out->extconn.cs.controller = ext_controller;
4845 out->extconn.cs.stream = ext_stream;
4846 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4847 use_case_table[out->usecase], out->extconn.cs.controller,
4848 out->extconn.cs.stream);
4849 }
4850
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004851 if (out == adev->primary_output) {
4852 pthread_mutex_lock(&adev->lock);
4853 audio_extn_set_parameters(adev, parms);
4854 pthread_mutex_unlock(&adev->lock);
4855 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004856 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004857 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004858 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004859
4860 audio_extn_dts_create_state_notifier_node(out->usecase);
4861 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4862 popcount(out->channel_mask),
4863 out->playback_started);
4864
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004865 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004866 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004867
Surendar Karkaf51b5842018-04-26 11:28:38 +05304868 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4869 sizeof(value));
4870 if (err >= 0) {
4871 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4872 audio_extn_send_dual_mono_mixing_coefficients(out);
4873 }
4874
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304875 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4876 if (err >= 0) {
4877 strlcpy(out->profile, value, sizeof(out->profile));
4878 ALOGV("updating stream profile with value '%s'", out->profile);
4879 lock_output_stream(out);
4880 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4881 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004882 &out->device_list, out->flags,
4883 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304884 out->sample_rate, out->bit_width,
4885 out->channel_mask, out->profile,
4886 &out->app_type_cfg);
4887 pthread_mutex_unlock(&out->lock);
4888 }
4889
Alexy Joseph98988832017-01-13 14:56:59 -08004890 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004891 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4892 // and vendor.audio.hal.output.suspend.supported is set to true
4893 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004894 //check suspend parameter only for low latency and if the property
4895 //is enabled
4896 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4897 ALOGI("%s: got suspend_playback %s", __func__, value);
4898 lock_output_stream(out);
4899 if (!strncmp(value, "false", 5)) {
4900 //suspend_playback=false is supposed to set QOS value back to 75%
4901 //the mixer control sent with value Enable will achieve that
4902 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4903 } else if (!strncmp (value, "true", 4)) {
4904 //suspend_playback=true is supposed to remove QOS value
4905 //resetting the mixer control will set the default value
4906 //for the mixer control which is Disable and this removes the QOS vote
4907 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4908 } else {
4909 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4910 " got %s", __func__, value);
4911 ret = -1;
4912 }
4913
4914 if (ret != 0) {
4915 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4916 __func__, out->pm_qos_mixer_path, ret);
4917 }
4918
4919 pthread_mutex_unlock(&out->lock);
4920 }
4921 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004922
Alexy Joseph98988832017-01-13 14:56:59 -08004923 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004924 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304925error:
Eric Laurent994a6932013-07-17 11:51:42 -07004926 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004927 return ret;
4928}
4929
Paul McLeana50b7332018-12-17 08:24:21 -07004930static int in_set_microphone_direction(const struct audio_stream_in *stream,
4931 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004932 struct stream_in *in = (struct stream_in *)stream;
4933
4934 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4935
4936 in->direction = dir;
4937
4938 if (in->standby)
4939 return 0;
4940
4941 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004942}
4943
4944static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004945 struct stream_in *in = (struct stream_in *)stream;
4946
4947 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4948
4949 if (zoom > 1.0 || zoom < -1.0)
4950 return -EINVAL;
4951
4952 in->zoom = zoom;
4953
4954 if (in->standby)
4955 return 0;
4956
4957 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004958}
4959
4960
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004961static bool stream_get_parameter_channels(struct str_parms *query,
4962 struct str_parms *reply,
4963 audio_channel_mask_t *supported_channel_masks) {
4964 int ret = -1;
4965 char value[512];
4966 bool first = true;
4967 size_t i, j;
4968
4969 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4970 ret = 0;
4971 value[0] = '\0';
4972 i = 0;
4973 while (supported_channel_masks[i] != 0) {
4974 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4975 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4976 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304977 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004978
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304979 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004980 first = false;
4981 break;
4982 }
4983 }
4984 i++;
4985 }
4986 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4987 }
4988 return ret == 0;
4989}
4990
4991static bool stream_get_parameter_formats(struct str_parms *query,
4992 struct str_parms *reply,
4993 audio_format_t *supported_formats) {
4994 int ret = -1;
4995 char value[256];
4996 size_t i, j;
4997 bool first = true;
4998
4999 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5000 ret = 0;
5001 value[0] = '\0';
5002 i = 0;
5003 while (supported_formats[i] != 0) {
5004 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5005 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5006 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305007 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005008 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305009 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005010 first = false;
5011 break;
5012 }
5013 }
5014 i++;
5015 }
5016 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5017 }
5018 return ret == 0;
5019}
5020
5021static bool stream_get_parameter_rates(struct str_parms *query,
5022 struct str_parms *reply,
5023 uint32_t *supported_sample_rates) {
5024
5025 int i;
5026 char value[256];
5027 int ret = -1;
5028 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5029 ret = 0;
5030 value[0] = '\0';
5031 i=0;
5032 int cursor = 0;
5033 while (supported_sample_rates[i]) {
5034 int avail = sizeof(value) - cursor;
5035 ret = snprintf(value + cursor, avail, "%s%d",
5036 cursor > 0 ? "|" : "",
5037 supported_sample_rates[i]);
5038 if (ret < 0 || ret >= avail) {
5039 // if cursor is at the last element of the array
5040 // overwrite with \0 is duplicate work as
5041 // snprintf already put a \0 in place.
5042 // else
5043 // we had space to write the '|' at value[cursor]
5044 // (which will be overwritten) or no space to fill
5045 // the first element (=> cursor == 0)
5046 value[cursor] = '\0';
5047 break;
5048 }
5049 cursor += ret;
5050 ++i;
5051 }
5052 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5053 value);
5054 }
5055 return ret >= 0;
5056}
5057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005058static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5059{
5060 struct stream_out *out = (struct stream_out *)stream;
5061 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005062 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005063 char value[256];
5064 struct str_parms *reply = str_parms_create();
5065 size_t i, j;
5066 int ret;
5067 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005068
5069 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005070 if (reply) {
5071 str_parms_destroy(reply);
5072 }
5073 if (query) {
5074 str_parms_destroy(query);
5075 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005076 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5077 return NULL;
5078 }
5079
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005080 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005081 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5082 if (ret >= 0) {
5083 value[0] = '\0';
5084 i = 0;
5085 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005086 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5087 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005088 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005089 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005090 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005091 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005092 first = false;
5093 break;
5094 }
5095 }
5096 i++;
5097 }
5098 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5099 str = str_parms_to_str(reply);
5100 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005101 voice_extn_out_get_parameters(out, query, reply);
5102 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005104
Alexy Joseph62142aa2015-11-16 15:10:34 -08005105
5106 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5107 if (ret >= 0) {
5108 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305109 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5110 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005111 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305112 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005113 } else {
5114 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305115 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005116 }
5117 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005118 if (str)
5119 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005120 str = str_parms_to_str(reply);
5121 }
5122
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005123 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5124 if (ret >= 0) {
5125 value[0] = '\0';
5126 i = 0;
5127 first = true;
5128 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005129 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5130 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005131 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005132 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005133 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005134 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005135 first = false;
5136 break;
5137 }
5138 }
5139 i++;
5140 }
5141 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005142 if (str)
5143 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005144 str = str_parms_to_str(reply);
5145 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005146
5147 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5148 if (ret >= 0) {
5149 value[0] = '\0';
5150 i = 0;
5151 first = true;
5152 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005153 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5154 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005155 if (!first) {
5156 strlcat(value, "|", sizeof(value));
5157 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005158 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005159 first = false;
5160 break;
5161 }
5162 }
5163 i++;
5164 }
5165 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5166 if (str)
5167 free(str);
5168 str = str_parms_to_str(reply);
5169 }
5170
Alexy Joseph98988832017-01-13 14:56:59 -08005171 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5172 //only low latency track supports suspend_resume
5173 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005174 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005175 if (str)
5176 free(str);
5177 str = str_parms_to_str(reply);
5178 }
5179
5180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005181 str_parms_destroy(query);
5182 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005183 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005184 return str;
5185}
5186
5187static uint32_t out_get_latency(const struct audio_stream_out *stream)
5188{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005189 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005190 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005191 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005192
Alexy Josephaa54c872014-12-03 02:46:47 -08005193 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305194 lock_output_stream(out);
5195 latency = audio_extn_utils_compress_get_dsp_latency(out);
5196 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005197 } else if ((out->realtime) ||
5198 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005199 // since the buffer won't be filled up faster than realtime,
5200 // return a smaller number
5201 if (out->config.rate)
5202 period_ms = (out->af_period_multiplier * out->config.period_size *
5203 1000) / (out->config.rate);
5204 else
5205 period_ms = 0;
5206 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005207 } else {
5208 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005209 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005210 }
5211
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005212 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005213 latency += audio_extn_a2dp_get_encoder_latency();
5214
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305215 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005216 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005217}
5218
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305219static float AmpToDb(float amplification)
5220{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305221 float db = DSD_VOLUME_MIN_DB;
5222 if (amplification > 0) {
5223 db = 20 * log10(amplification);
5224 if(db < DSD_VOLUME_MIN_DB)
5225 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305226 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305227 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305228}
5229
Arun Mirpuri5d170872019-03-26 13:21:31 -07005230static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5231 float right)
5232{
5233 struct stream_out *out = (struct stream_out *)stream;
5234 long volume = 0;
5235 char mixer_ctl_name[128] = "";
5236 struct audio_device *adev = out->dev;
5237 struct mixer_ctl *ctl = NULL;
5238 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5239 PCM_PLAYBACK);
5240
5241 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5242 "Playback %d Volume", pcm_device_id);
5243 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5244 if (!ctl) {
5245 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5246 __func__, mixer_ctl_name);
5247 return -EINVAL;
5248 }
5249 if (left != right)
5250 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5251 __func__, left, right);
5252 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5253 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5254 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5255 __func__, mixer_ctl_name, volume);
5256 return -EINVAL;
5257 }
5258 return 0;
5259}
5260
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305261static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5262 float right)
5263{
5264 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305265 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305266 char mixer_ctl_name[128];
5267 struct audio_device *adev = out->dev;
5268 struct mixer_ctl *ctl;
5269 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5270 PCM_PLAYBACK);
5271
5272 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5273 "Compress Playback %d Volume", pcm_device_id);
5274 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5275 if (!ctl) {
5276 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5277 __func__, mixer_ctl_name);
5278 return -EINVAL;
5279 }
5280 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5281 __func__, mixer_ctl_name, left, right);
5282 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5283 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5284 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5285
5286 return 0;
5287}
5288
Zhou Song2b8f28f2017-09-11 10:51:38 +08005289static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5290 float right)
5291{
5292 struct stream_out *out = (struct stream_out *)stream;
5293 char mixer_ctl_name[] = "App Type Gain";
5294 struct audio_device *adev = out->dev;
5295 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305296 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005297
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005298 if (!is_valid_volume(left, right)) {
5299 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5300 __func__, left, right);
5301 return -EINVAL;
5302 }
5303
Zhou Song2b8f28f2017-09-11 10:51:38 +08005304 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5305 if (!ctl) {
5306 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5307 __func__, mixer_ctl_name);
5308 return -EINVAL;
5309 }
5310
5311 set_values[0] = 0; //0: Rx Session 1:Tx Session
5312 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305313 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5314 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005315
5316 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5317 return 0;
5318}
5319
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305320static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5321 float right)
5322{
5323 struct stream_out *out = (struct stream_out *)stream;
5324 /* Volume control for pcm playback */
5325 if (left != right) {
5326 return -EINVAL;
5327 } else {
5328 char mixer_ctl_name[128];
5329 struct audio_device *adev = out->dev;
5330 struct mixer_ctl *ctl;
5331 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5332 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5333 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5334 if (!ctl) {
5335 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5336 return -EINVAL;
5337 }
5338
5339 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5340 int ret = mixer_ctl_set_value(ctl, 0, volume);
5341 if (ret < 0) {
5342 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5343 return -EINVAL;
5344 }
5345
5346 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5347
5348 return 0;
5349 }
5350}
5351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005352static int out_set_volume(struct audio_stream_out *stream, float left,
5353 float right)
5354{
Eric Laurenta9024de2013-04-04 09:19:12 -07005355 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005356 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305357 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005358
Arun Mirpuri5d170872019-03-26 13:21:31 -07005359 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005360 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5361 /* only take left channel into account: the API is for stereo anyway */
5362 out->muted = (left == 0.0f);
5363 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005364 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305365 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005366 /*
5367 * Set mute or umute on HDMI passthrough stream.
5368 * Only take left channel into account.
5369 * Mute is 0 and unmute 1
5370 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305371 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305372 } else if (out->format == AUDIO_FORMAT_DSD){
5373 char mixer_ctl_name[128] = "DSD Volume";
5374 struct audio_device *adev = out->dev;
5375 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5376
5377 if (!ctl) {
5378 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5379 __func__, mixer_ctl_name);
5380 return -EINVAL;
5381 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305382 volume[0] = (long)(AmpToDb(left));
5383 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305384 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5385 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005386 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005387 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005388 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5389 struct listnode *node = NULL;
5390 list_for_each(node, &adev->active_outputs_list) {
5391 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5392 streams_output_ctxt_t,
5393 list);
5394 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5395 out->volume_l = out_ctxt->output->volume_l;
5396 out->volume_r = out_ctxt->output->volume_r;
5397 }
5398 }
5399 if (!out->a2dp_compress_mute) {
5400 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5401 }
5402 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005403 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305404 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005405 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305406 if (!out->a2dp_compress_mute)
5407 ret = out_set_compr_volume(stream, left, right);
5408 out->volume_l = left;
5409 out->volume_r = right;
5410 pthread_mutex_unlock(&out->compr_mute_lock);
5411 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005412 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005413 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005414 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5415 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5416 if (!out->standby) {
5417 audio_extn_utils_send_app_type_gain(out->dev,
5418 out->app_type_cfg.app_type,
5419 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005420 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005421 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005422 out->volume_l = left;
5423 out->volume_r = right;
5424 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005425 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5426 ALOGV("%s: MMAP set volume called", __func__);
5427 if (!out->standby)
5428 ret = out_set_mmap_volume(stream, left, right);
5429 out->volume_l = left;
5430 out->volume_r = right;
5431 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305432 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305433 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5434 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305435 /* Volume control for pcm playback */
5436 if (!out->standby)
5437 ret = out_set_pcm_volume(stream, left, right);
5438 else
5439 out->apply_volume = true;
5440
5441 out->volume_l = left;
5442 out->volume_r = right;
5443 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005444 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5445 ALOGV("%s: bus device set volume called", __func__);
5446 if (!out->standby)
5447 ret = out_set_pcm_volume(stream, left, right);
5448 out->volume_l = left;
5449 out->volume_r = right;
5450 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005451 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005452
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005453 return -ENOSYS;
5454}
5455
Zhou Songc9672822017-08-16 16:01:39 +08005456static void update_frames_written(struct stream_out *out, size_t bytes)
5457{
5458 size_t bpf = 0;
5459
5460 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5461 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5462 bpf = 1;
5463 else if (!is_offload_usecase(out->usecase))
5464 bpf = audio_bytes_per_sample(out->format) *
5465 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005466
5467 pthread_mutex_lock(&out->position_query_lock);
5468 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005469 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005470 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5471 }
5472 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005473}
5474
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005475int split_and_write_audio_haptic_data(struct stream_out *out,
5476 const void *buffer, size_t bytes_to_write)
5477{
5478 struct audio_device *adev = out->dev;
5479
5480 int ret = 0;
5481 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5482 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5483 size_t frame_size = channel_count * bytes_per_sample;
5484 size_t frame_count = bytes_to_write / frame_size;
5485
5486 bool force_haptic_path =
5487 property_get_bool("vendor.audio.test_haptic", false);
5488
5489 // extract Haptics data from Audio buffer
5490 bool alloc_haptic_buffer = false;
5491 int haptic_channel_count = adev->haptics_config.channels;
5492 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5493 size_t audio_frame_size = frame_size - haptic_frame_size;
5494 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5495
5496 if (adev->haptic_buffer == NULL) {
5497 alloc_haptic_buffer = true;
5498 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5499 free(adev->haptic_buffer);
5500 adev->haptic_buffer_size = 0;
5501 alloc_haptic_buffer = true;
5502 }
5503
5504 if (alloc_haptic_buffer) {
5505 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005506 if(adev->haptic_buffer == NULL) {
5507 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5508 return -ENOMEM;
5509 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005510 adev->haptic_buffer_size = total_haptic_buffer_size;
5511 }
5512
5513 size_t src_index = 0, aud_index = 0, hap_index = 0;
5514 uint8_t *audio_buffer = (uint8_t *)buffer;
5515 uint8_t *haptic_buffer = adev->haptic_buffer;
5516
5517 // This is required for testing only. This works for stereo data only.
5518 // One channel is fed to audio stream and other to haptic stream for testing.
5519 if (force_haptic_path)
5520 audio_frame_size = haptic_frame_size = bytes_per_sample;
5521
5522 for (size_t i = 0; i < frame_count; i++) {
5523 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5524 audio_frame_size);
5525 aud_index += audio_frame_size;
5526 src_index += audio_frame_size;
5527
5528 if (adev->haptic_pcm)
5529 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5530 haptic_frame_size);
5531 hap_index += haptic_frame_size;
5532 src_index += haptic_frame_size;
5533
5534 // This is required for testing only.
5535 // Discard haptic channel data.
5536 if (force_haptic_path)
5537 src_index += haptic_frame_size;
5538 }
5539
5540 // write to audio pipeline
5541 ret = pcm_write(out->pcm, (void *)audio_buffer,
5542 frame_count * audio_frame_size);
5543
5544 // write to haptics pipeline
5545 if (adev->haptic_pcm)
5546 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5547 frame_count * haptic_frame_size);
5548
5549 return ret;
5550}
5551
Aalique Grahame22e49102018-12-18 14:23:57 -08005552#ifdef NO_AUDIO_OUT
5553static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5554 const void *buffer __unused, size_t bytes)
5555{
5556 struct stream_out *out = (struct stream_out *)stream;
5557
5558 /* No Output device supported other than BT for playback.
5559 * Sleep for the amount of buffer duration
5560 */
5561 lock_output_stream(out);
5562 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5563 (const struct audio_stream_out *)&out->stream) /
5564 out_get_sample_rate(&out->stream.common));
5565 pthread_mutex_unlock(&out->lock);
5566 return bytes;
5567}
5568#endif
5569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005570static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5571 size_t bytes)
5572{
5573 struct stream_out *out = (struct stream_out *)stream;
5574 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005575 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305576 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005577 const size_t frame_size = audio_stream_out_frame_size(stream);
5578 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305579 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005580 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005581
Haynes Mathew George380745d2017-10-04 15:27:45 -07005582 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005583 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305584
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305585 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005586
Dhananjay Kumarac341582017-02-23 23:42:25 +05305587 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305588 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305589 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5590 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005591 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305592 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305593 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305594 ALOGD(" %s: sound card is not active/SSR state", __func__);
5595 ret= -EIO;
5596 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305597 }
5598 }
5599
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305600 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305601 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305602 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305603 goto exit;
5604 }
5605
Haynes Mathew George16081042017-05-31 17:16:49 -07005606 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5607 ret = -EINVAL;
5608 goto exit;
5609 }
5610
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005611 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305612 !out->is_iec61937_info_available) {
5613
5614 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5615 out->is_iec61937_info_available = true;
5616 } else if (audio_extn_passthru_is_enabled()) {
5617 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305618 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305619
5620 if((out->format == AUDIO_FORMAT_DTS) ||
5621 (out->format == AUDIO_FORMAT_DTS_HD)) {
5622 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5623 buffer, bytes);
5624 if (ret) {
5625 if (ret != -ENOSYS) {
5626 out->is_iec61937_info_available = false;
5627 ALOGD("iec61937 transmission info not yet updated retry");
5628 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305629 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305630 /* if stream has started and after that there is
5631 * stream config change (iec transmission config)
5632 * then trigger select_device to update backend configuration.
5633 */
5634 out->stream_config_changed = true;
5635 pthread_mutex_lock(&adev->lock);
5636 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305637 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005638 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305639 ret = -EINVAL;
5640 goto exit;
5641 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305642 pthread_mutex_unlock(&adev->lock);
5643 out->stream_config_changed = false;
5644 out->is_iec61937_info_available = true;
5645 }
5646 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305647
Meng Wang4c32fb42020-01-16 17:57:11 +08005648#ifdef AUDIO_GKI_ENABLED
5649 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5650 compr_passthr = out->compr_config.codec->reserved[0];
5651#else
5652 compr_passthr = out->compr_config.codec->compr_passthr;
5653#endif
5654
Garmond Leung317cbf12017-09-13 16:20:50 -07005655 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005656 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305657 (out->is_iec61937_info_available == true)) {
5658 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5659 ret = -EINVAL;
5660 goto exit;
5661 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305662 }
5663 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305664
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005665 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005666 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005667 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5668 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305669 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305670 ret = -EIO;
5671 goto exit;
5672 }
5673 }
5674 }
5675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005676 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005677 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005678 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005679 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5680 ret = voice_extn_compress_voip_start_output_stream(out);
5681 else
5682 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005683 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005684 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005685 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005686 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005687 goto exit;
5688 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305689 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005690 if (last_known_cal_step != -1) {
5691 ALOGD("%s: retry previous failed cal level set", __func__);
5692 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305693 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005694 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305695
5696 if ((out->is_iec61937_info_available == true) &&
5697 (audio_extn_passthru_is_passthrough_stream(out))&&
5698 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5699 ret = -EINVAL;
5700 goto exit;
5701 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305702 if (out->set_dual_mono)
5703 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005704 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005705
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005706 if (adev->is_channel_status_set == false &&
5707 compare_device_type(&out->device_list,
5708 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005709 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305710 adev->is_channel_status_set = true;
5711 }
5712
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305713 if ((adev->use_old_pspd_mix_ctrl == true) &&
5714 (out->pspd_coeff_sent == false)) {
5715 /*
5716 * Need to resend pspd coefficients after stream started for
5717 * older kernel version as it does not save the coefficients
5718 * and also stream has to be started for coeff to apply.
5719 */
5720 usecase = get_usecase_from_list(adev, out->usecase);
5721 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305722 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305723 out->pspd_coeff_sent = true;
5724 }
5725 }
5726
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005727 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005728 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005729 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005730 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005731 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5732 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305733 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5734 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005735 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305736 out->send_next_track_params = false;
5737 out->is_compr_metadata_avail = false;
5738 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005739 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305740 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305741 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005742
Ashish Jain83a6cc22016-06-28 14:34:17 +05305743 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305744 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305745 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305746 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005747 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305748 return -EINVAL;
5749 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305750 audio_format_t dst_format = out->hal_op_format;
5751 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305752
Dieter Luecking5d57def2018-09-07 14:23:37 +02005753 /* prevent division-by-zero */
5754 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5755 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5756 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5757 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305758 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005759 ATRACE_END();
5760 return -EINVAL;
5761 }
5762
Ashish Jainf1eaa582016-05-23 20:54:24 +05305763 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5764 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5765
Ashish Jain83a6cc22016-06-28 14:34:17 +05305766 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305767 dst_format,
5768 buffer,
5769 src_format,
5770 frames);
5771
Ashish Jain83a6cc22016-06-28 14:34:17 +05305772 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305773 bytes_to_write);
5774
5775 /*Convert written bytes in audio flinger format*/
5776 if (ret > 0)
5777 ret = ((ret * format_to_bitwidth_table[out->format]) /
5778 format_to_bitwidth_table[dst_format]);
5779 }
5780 } else
5781 ret = compress_write(out->compr, buffer, bytes);
5782
Zhou Songc9672822017-08-16 16:01:39 +08005783 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5784 update_frames_written(out, bytes);
5785
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305786 if (ret < 0)
5787 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005788 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305789 /*msg to cb thread only if non blocking write is enabled*/
5790 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305791 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005792 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305793 } else if (-ENETRESET == ret) {
5794 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305795 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305796 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305797 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005798 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305799 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005800 }
Ashish Jain5106d362016-05-11 19:23:33 +05305801
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305802 /* Call compr start only when non-zero bytes of data is there to be rendered */
5803 if (!out->playback_started && ret > 0) {
5804 int status = compress_start(out->compr);
5805 if (status < 0) {
5806 ret = status;
5807 ALOGE("%s: compr start failed with err %d", __func__, errno);
5808 goto exit;
5809 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005810 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005811 out->playback_started = 1;
5812 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005813
5814 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5815 popcount(out->channel_mask),
5816 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005817 }
5818 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005819 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005820 return ret;
5821 } else {
5822 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005823 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005824 if (out->muted)
5825 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005826 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5827 __func__, frames, frame_size, bytes_to_write);
5828
Aalique Grahame22e49102018-12-18 14:23:57 -08005829 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005830 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5831 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5832 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005833 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5834 int16_t *src = (int16_t *)buffer;
5835 int16_t *dst = (int16_t *)buffer;
5836
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005837 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005838 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005839 "out_write called for %s use case with wrong properties",
5840 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005841
5842 /*
5843 * FIXME: this can be removed once audio flinger mixer supports
5844 * mono output
5845 */
5846
5847 /*
5848 * Code below goes over each frame in the buffer and adds both
5849 * L and R samples and then divides by 2 to convert to mono
5850 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005851 if (channel_count == 2) {
5852 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5853 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5854 }
5855 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005856 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005857 }
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305858 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005859
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005860 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005861
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005862 if (out->config.rate)
5863 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5864 out->config.rate;
5865
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005866 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005867 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5868
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005869 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005870 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005871 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305872 out->convert_buffer != NULL) {
5873
5874 memcpy_by_audio_format(out->convert_buffer,
5875 out->hal_op_format,
5876 buffer,
5877 out->hal_ip_format,
5878 out->config.period_size * out->config.channels);
5879
5880 ret = pcm_write(out->pcm, out->convert_buffer,
5881 (out->config.period_size *
5882 out->config.channels *
5883 format_to_bitwidth_table[out->hal_op_format]));
5884 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305885 /*
5886 * To avoid underrun in DSP when the application is not pumping
5887 * data at required rate, check for the no. of bytes and ignore
5888 * pcm_write if it is less than actual buffer size.
5889 * It is a work around to a change in compress VOIP driver.
5890 */
5891 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5892 bytes < (out->config.period_size * out->config.channels *
5893 audio_bytes_per_sample(out->format))) {
5894 size_t voip_buf_size =
5895 out->config.period_size * out->config.channels *
5896 audio_bytes_per_sample(out->format);
5897 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5898 __func__, bytes, voip_buf_size);
5899 usleep(((uint64_t)voip_buf_size - bytes) *
5900 1000000 / audio_stream_out_frame_size(stream) /
5901 out_get_sample_rate(&out->stream.common));
5902 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005903 } else {
5904 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5905 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5906 else
5907 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5908 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305909 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005910
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005911 release_out_focus(out);
5912
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305913 if (ret < 0)
5914 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005915 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305916 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005917 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005918 }
5919
5920exit:
Zhou Songc9672822017-08-16 16:01:39 +08005921 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305922 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305923 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305924 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005925 pthread_mutex_unlock(&out->lock);
5926
5927 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005928 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005929 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305930 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305931 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305932 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305933 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305934 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305935 out->standby = true;
5936 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305937 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005938 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5939 /* prevent division-by-zero */
5940 uint32_t stream_size = audio_stream_out_frame_size(stream);
5941 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005942
Dieter Luecking5d57def2018-09-07 14:23:37 +02005943 if ((stream_size == 0) || (srate == 0)) {
5944 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5945 ATRACE_END();
5946 return -EINVAL;
5947 }
5948 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5949 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005950 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305951 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005952 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005953 return ret;
5954 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005955 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005956 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005957 return bytes;
5958}
5959
5960static int out_get_render_position(const struct audio_stream_out *stream,
5961 uint32_t *dsp_frames)
5962{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005963 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005964
5965 if (dsp_frames == NULL)
5966 return -EINVAL;
5967
5968 *dsp_frames = 0;
5969 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005970 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305971
5972 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5973 * this operation and adev_close_output_stream(where out gets reset).
5974 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305975 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005976 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305977 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005978 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305979 return 0;
5980 }
5981
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005982 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305983 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305984 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005985 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305986 if (ret < 0)
5987 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005988 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305989 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005990 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305991 if (-ENETRESET == ret) {
5992 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305993 out->card_status = CARD_STATUS_OFFLINE;
5994 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305995 } else if(ret < 0) {
5996 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305997 ret = -EINVAL;
5998 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305999 /*
6000 * Handle corner case where compress session is closed during SSR
6001 * and timestamp is queried
6002 */
6003 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306004 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306005 } else if (out->prev_card_status_offline) {
6006 ALOGE("ERROR: previously sound card was offline,return error");
6007 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306008 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306009 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006010 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306011 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306012 pthread_mutex_unlock(&out->lock);
6013 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006014 } else if (audio_is_linear_pcm(out->format)) {
6015 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006016 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006017 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006018 } else
6019 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006020}
6021
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006022static int out_add_audio_effect(const struct audio_stream *stream __unused,
6023 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006024{
6025 return 0;
6026}
6027
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006028static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6029 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006030{
6031 return 0;
6032}
6033
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006034static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6035 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006036{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306037 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006038}
6039
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006040static int out_get_presentation_position(const struct audio_stream_out *stream,
6041 uint64_t *frames, struct timespec *timestamp)
6042{
6043 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306044 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006045 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006046
Ashish Jain5106d362016-05-11 19:23:33 +05306047 /* below piece of code is not guarded against any lock because audioFliner serializes
6048 * this operation and adev_close_output_stream( where out gets reset).
6049 */
6050 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306051 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006052 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306053 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6054 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6055 return 0;
6056 }
6057
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006058 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006059
Ashish Jain5106d362016-05-11 19:23:33 +05306060 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6061 ret = compress_get_tstamp(out->compr, &dsp_frames,
6062 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006063 // Adjustment accounts for A2dp encoder latency with offload usecases
6064 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006065 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006066 unsigned long offset =
6067 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6068 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6069 }
Ashish Jain5106d362016-05-11 19:23:33 +05306070 ALOGVV("%s rendered frames %ld sample_rate %d",
6071 __func__, dsp_frames, out->sample_rate);
6072 *frames = dsp_frames;
6073 if (ret < 0)
6074 ret = -errno;
6075 if (-ENETRESET == ret) {
6076 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306077 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306078 ret = -EINVAL;
6079 } else
6080 ret = 0;
6081 /* this is the best we can do */
6082 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006083 } else {
6084 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006085 unsigned int avail;
6086 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
6087 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
George Gao62ebc722019-07-29 16:29:44 -07006088
6089 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006090 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006091
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006092 frames_temp = (kernel_buffer_size > avail) ? (kernel_buffer_size - avail) : 0;
6093 if (out->written >= frames_temp)
6094 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006095
Weiyin Jiangd4633762018-03-16 12:05:03 +08006096 // This adjustment accounts for buffering after app processor.
6097 // It is based on estimated DSP latency per use case, rather than exact.
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006098 frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL;
6099 if (signed_frames >= frames_temp)
6100 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006101
Weiyin Jiangd4633762018-03-16 12:05:03 +08006102 // Adjustment accounts for A2dp encoder latency with non offload usecases
6103 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006104 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006105 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6106 if (signed_frames >= frames_temp)
6107 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006108 }
6109
6110 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006111 *frames = signed_frames;
6112 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006113 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306114 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306115 *frames = out->written;
6116 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306117 if (is_offload_usecase(out->usecase))
6118 ret = -EINVAL;
6119 else
6120 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006121 }
6122 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006123 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006124 return ret;
6125}
6126
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006127static int out_set_callback(struct audio_stream_out *stream,
6128 stream_callback_t callback, void *cookie)
6129{
6130 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006131 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006132
6133 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006134 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006135 out->client_callback = callback;
6136 out->client_cookie = cookie;
6137 if (out->adsp_hdlr_stream_handle) {
6138 ret = audio_extn_adsp_hdlr_stream_set_callback(
6139 out->adsp_hdlr_stream_handle,
6140 callback,
6141 cookie);
6142 if (ret)
6143 ALOGW("%s:adsp hdlr callback registration failed %d",
6144 __func__, ret);
6145 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006146 pthread_mutex_unlock(&out->lock);
6147 return 0;
6148}
6149
6150static int out_pause(struct audio_stream_out* stream)
6151{
6152 struct stream_out *out = (struct stream_out *)stream;
6153 int status = -ENOSYS;
6154 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006155 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006156 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006157 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006158 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306159 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306160 status = compress_pause(out->compr);
6161
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006162 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006163
Mingming Yin21854652016-04-13 11:54:02 -07006164 if (audio_extn_passthru_is_active()) {
6165 ALOGV("offload use case, pause passthru");
6166 audio_extn_passthru_on_pause(out);
6167 }
6168
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306169 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006170 audio_extn_dts_notify_playback_state(out->usecase, 0,
6171 out->sample_rate, popcount(out->channel_mask),
6172 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006173 }
6174 pthread_mutex_unlock(&out->lock);
6175 }
6176 return status;
6177}
6178
6179static int out_resume(struct audio_stream_out* stream)
6180{
6181 struct stream_out *out = (struct stream_out *)stream;
6182 int status = -ENOSYS;
6183 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006184 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006185 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006186 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006187 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006188 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306189 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306190 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006191 }
6192 if (!status) {
6193 out->offload_state = OFFLOAD_STATE_PLAYING;
6194 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306195 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006196 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6197 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006198 }
6199 pthread_mutex_unlock(&out->lock);
6200 }
6201 return status;
6202}
6203
6204static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6205{
6206 struct stream_out *out = (struct stream_out *)stream;
6207 int status = -ENOSYS;
6208 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006209 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006210 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006211 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6212 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6213 else
6214 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6215 pthread_mutex_unlock(&out->lock);
6216 }
6217 return status;
6218}
6219
6220static int out_flush(struct audio_stream_out* stream)
6221{
6222 struct stream_out *out = (struct stream_out *)stream;
6223 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006224 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006225 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006226 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006227 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6228 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006229 } else {
6230 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6231 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006232 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006233 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006234 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006235 return 0;
6236 }
6237 return -ENOSYS;
6238}
6239
Haynes Mathew George16081042017-05-31 17:16:49 -07006240static int out_stop(const struct audio_stream_out* stream)
6241{
6242 struct stream_out *out = (struct stream_out *)stream;
6243 struct audio_device *adev = out->dev;
6244 int ret = -ENOSYS;
6245
6246 ALOGV("%s", __func__);
6247 pthread_mutex_lock(&adev->lock);
6248 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6249 out->playback_started && out->pcm != NULL) {
6250 pcm_stop(out->pcm);
6251 ret = stop_output_stream(out);
6252 out->playback_started = false;
6253 }
6254 pthread_mutex_unlock(&adev->lock);
6255 return ret;
6256}
6257
6258static int out_start(const struct audio_stream_out* stream)
6259{
6260 struct stream_out *out = (struct stream_out *)stream;
6261 struct audio_device *adev = out->dev;
6262 int ret = -ENOSYS;
6263
6264 ALOGV("%s", __func__);
6265 pthread_mutex_lock(&adev->lock);
6266 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6267 !out->playback_started && out->pcm != NULL) {
6268 ret = start_output_stream(out);
6269 if (ret == 0) {
6270 out->playback_started = true;
6271 }
6272 }
6273 pthread_mutex_unlock(&adev->lock);
6274 return ret;
6275}
6276
6277/*
6278 * Modify config->period_count based on min_size_frames
6279 */
6280static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6281{
6282 int periodCountRequested = (min_size_frames + config->period_size - 1)
6283 / config->period_size;
6284 int periodCount = MMAP_PERIOD_COUNT_MIN;
6285
6286 ALOGV("%s original config.period_size = %d config.period_count = %d",
6287 __func__, config->period_size, config->period_count);
6288
6289 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6290 periodCount *= 2;
6291 }
6292 config->period_count = periodCount;
6293
6294 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6295}
6296
Phil Burkfe17efd2019-03-25 10:23:35 -07006297// Read offset for the positional timestamp from a persistent vendor property.
6298// This is to workaround apparent inaccuracies in the timing information that
6299// is used by the AAudio timing model. The inaccuracies can cause glitches.
6300static int64_t get_mmap_out_time_offset() {
6301 const int32_t kDefaultOffsetMicros = 0;
6302 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006303 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006304 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6305 return mmap_time_offset_micros * (int64_t)1000;
6306}
6307
Haynes Mathew George16081042017-05-31 17:16:49 -07006308static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6309 int32_t min_size_frames,
6310 struct audio_mmap_buffer_info *info)
6311{
6312 struct stream_out *out = (struct stream_out *)stream;
6313 struct audio_device *adev = out->dev;
6314 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006315 unsigned int offset1 = 0;
6316 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006317 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006318 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006319 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006320
Arun Mirpuri5d170872019-03-26 13:21:31 -07006321 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306322 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006323 pthread_mutex_lock(&adev->lock);
6324
Sharad Sanglec6f32552018-05-04 16:15:38 +05306325 if (CARD_STATUS_OFFLINE == out->card_status ||
6326 CARD_STATUS_OFFLINE == adev->card_status) {
6327 ALOGW("out->card_status or adev->card_status offline, try again");
6328 ret = -EIO;
6329 goto exit;
6330 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006331 if (info == NULL || min_size_frames == 0) {
6332 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6333 ret = -EINVAL;
6334 goto exit;
6335 }
6336 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6337 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6338 ret = -ENOSYS;
6339 goto exit;
6340 }
6341 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6342 if (out->pcm_device_id < 0) {
6343 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6344 __func__, out->pcm_device_id, out->usecase);
6345 ret = -EINVAL;
6346 goto exit;
6347 }
6348
6349 adjust_mmap_period_count(&out->config, min_size_frames);
6350
Arun Mirpuri5d170872019-03-26 13:21:31 -07006351 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006352 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6353 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6354 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306355 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306356 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6357 out->card_status = CARD_STATUS_OFFLINE;
6358 adev->card_status = CARD_STATUS_OFFLINE;
6359 ret = -EIO;
6360 goto exit;
6361 }
6362
Haynes Mathew George16081042017-05-31 17:16:49 -07006363 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6364 step = "open";
6365 ret = -ENODEV;
6366 goto exit;
6367 }
6368 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6369 if (ret < 0) {
6370 step = "begin";
6371 goto exit;
6372 }
6373 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006374 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006375 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006376 ret = platform_get_mmap_data_fd(adev->platform,
6377 out->pcm_device_id, 0 /*playback*/,
6378 &info->shared_memory_fd,
6379 &mmap_size);
6380 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006381 // Fall back to non exclusive mode
6382 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6383 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006384 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6385 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6386
Arun Mirpuri5d170872019-03-26 13:21:31 -07006387 if (mmap_size < buffer_size) {
6388 step = "mmap";
6389 goto exit;
6390 }
6391 // FIXME: indicate exclusive mode support by returning a negative buffer size
6392 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006393 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006394 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006395 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006396
6397 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6398 if (ret < 0) {
6399 step = "commit";
6400 goto exit;
6401 }
6402
Phil Burkfe17efd2019-03-25 10:23:35 -07006403 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6404
Haynes Mathew George16081042017-05-31 17:16:49 -07006405 out->standby = false;
6406 ret = 0;
6407
Arun Mirpuri5d170872019-03-26 13:21:31 -07006408 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006409 __func__, info->shared_memory_address, info->buffer_size_frames);
6410
6411exit:
6412 if (ret != 0) {
6413 if (out->pcm == NULL) {
6414 ALOGE("%s: %s - %d", __func__, step, ret);
6415 } else {
6416 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6417 pcm_close(out->pcm);
6418 out->pcm = NULL;
6419 }
6420 }
6421 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306422 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006423 return ret;
6424}
6425
6426static int out_get_mmap_position(const struct audio_stream_out *stream,
6427 struct audio_mmap_position *position)
6428{
6429 struct stream_out *out = (struct stream_out *)stream;
6430 ALOGVV("%s", __func__);
6431 if (position == NULL) {
6432 return -EINVAL;
6433 }
6434 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006435 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006436 return -ENOSYS;
6437 }
6438 if (out->pcm == NULL) {
6439 return -ENOSYS;
6440 }
6441
6442 struct timespec ts = { 0, 0 };
6443 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6444 if (ret < 0) {
6445 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6446 return ret;
6447 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006448 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6449 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006450 return 0;
6451}
6452
6453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006454/** audio_stream_in implementation **/
6455static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6456{
6457 struct stream_in *in = (struct stream_in *)stream;
6458
6459 return in->config.rate;
6460}
6461
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006462static int in_set_sample_rate(struct audio_stream *stream __unused,
6463 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006464{
6465 return -ENOSYS;
6466}
6467
6468static size_t in_get_buffer_size(const struct audio_stream *stream)
6469{
6470 struct stream_in *in = (struct stream_in *)stream;
6471
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006472 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6473 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006474 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6475 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306476 else if(audio_extn_cin_attached_usecase(in->usecase))
6477 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006478
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006479 return in->config.period_size * in->af_period_multiplier *
6480 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006481}
6482
6483static uint32_t in_get_channels(const struct audio_stream *stream)
6484{
6485 struct stream_in *in = (struct stream_in *)stream;
6486
6487 return in->channel_mask;
6488}
6489
6490static audio_format_t in_get_format(const struct audio_stream *stream)
6491{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006492 struct stream_in *in = (struct stream_in *)stream;
6493
6494 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006495}
6496
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006497static int in_set_format(struct audio_stream *stream __unused,
6498 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006499{
6500 return -ENOSYS;
6501}
6502
6503static int in_standby(struct audio_stream *stream)
6504{
6505 struct stream_in *in = (struct stream_in *)stream;
6506 struct audio_device *adev = in->dev;
6507 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306508 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6509 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006510 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306511
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006512 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006513 if (!in->standby && in->is_st_session) {
6514 ALOGD("%s: sound trigger pcm stop lab", __func__);
6515 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006516 if (adev->num_va_sessions > 0)
6517 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006518 in->standby = 1;
6519 }
6520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006521 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006522 if (adev->adm_deregister_stream)
6523 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6524
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006525 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006526 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006527 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006528 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006529 voice_extn_compress_voip_close_input_stream(stream);
6530 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006531 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6532 do_stop = in->capture_started;
6533 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006534 if (in->mmap_shared_memory_fd >= 0) {
6535 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6536 __func__, in->mmap_shared_memory_fd);
6537 close(in->mmap_shared_memory_fd);
6538 in->mmap_shared_memory_fd = -1;
6539 }
Zhou Songa8895042016-07-05 17:54:22 +08006540 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306541 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05306542 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006543 }
6544
Arun Mirpuri5d170872019-03-26 13:21:31 -07006545 if (in->pcm) {
6546 ATRACE_BEGIN("pcm_in_close");
6547 pcm_close(in->pcm);
6548 ATRACE_END();
6549 in->pcm = NULL;
6550 }
6551
Carter Hsu2e429db2019-05-14 18:50:52 +08006552 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
Aalique Grahame22e49102018-12-18 14:23:57 -08006553 adev->enable_voicerx = false;
Carter Hsu2e429db2019-05-14 18:50:52 +08006554
6555 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006556 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006557
George Gao3018ede2019-10-23 13:23:00 -07006558 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6559 if (adev->num_va_sessions > 0)
6560 adev->num_va_sessions--;
6561 }
Quinn Malef6050362019-01-30 15:55:40 -08006562
Eric Laurent150dbfe2013-02-27 14:31:02 -08006563 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006564 }
6565 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006566 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006567 return status;
6568}
6569
Aalique Grahame22e49102018-12-18 14:23:57 -08006570static int in_dump(const struct audio_stream *stream,
6571 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006572{
Aalique Grahame22e49102018-12-18 14:23:57 -08006573 struct stream_in *in = (struct stream_in *)stream;
6574
6575 // We try to get the lock for consistency,
6576 // but it isn't necessary for these variables.
6577 // If we're not in standby, we may be blocked on a read.
6578 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6579 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6580 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6581 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6582
6583 if (locked) {
6584 pthread_mutex_unlock(&in->lock);
6585 }
6586
6587 // dump error info
6588 (void)error_log_dump(
6589 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006591 return 0;
6592}
6593
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306594static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6595{
6596 if (!stream || !parms)
6597 return;
6598
6599 struct stream_in *in = (struct stream_in *)stream;
6600 struct audio_device *adev = in->dev;
6601
6602 card_status_t status;
6603 int card;
6604 if (parse_snd_card_status(parms, &card, &status) < 0)
6605 return;
6606
6607 pthread_mutex_lock(&adev->lock);
6608 bool valid_cb = (card == adev->snd_card);
6609 pthread_mutex_unlock(&adev->lock);
6610
6611 if (!valid_cb)
6612 return;
6613
6614 lock_input_stream(in);
6615 if (in->card_status != status)
6616 in->card_status = status;
6617 pthread_mutex_unlock(&in->lock);
6618
6619 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6620 use_case_table[in->usecase],
6621 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6622
6623 // a better solution would be to report error back to AF and let
6624 // it put the stream to standby
6625 if (status == CARD_STATUS_OFFLINE)
6626 in_standby(&in->stream.common);
6627
6628 return;
6629}
6630
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006631int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006632 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006633 audio_source_t source)
6634{
6635 struct audio_device *adev = in->dev;
6636 int ret = 0;
6637
6638 lock_input_stream(in);
6639 pthread_mutex_lock(&adev->lock);
6640
6641 /* no audio source uses val == 0 */
6642 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6643 in->source = source;
6644 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6645 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6646 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6647 (in->config.rate == 8000 || in->config.rate == 16000 ||
6648 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6649 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6650 ret = voice_extn_compress_voip_open_input_stream(in);
6651 if (ret != 0) {
6652 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6653 __func__, ret);
6654 }
6655 }
6656 }
6657
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006658 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6659 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006660 // Workaround: If routing to an non existing usb device, fail gracefully
6661 // The routing request will otherwise block during 10 second
6662 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006663 struct str_parms *usb_addr =
6664 str_parms_create_str(get_usb_device_address(devices));
6665 if (is_usb_in_device_type(devices) && usb_addr &&
6666 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006667 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6668 ret = -ENOSYS;
6669 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006670 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006671 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006672 if (!in->standby && !in->is_st_session) {
6673 ALOGV("update input routing change");
6674 // inform adm before actual routing to prevent glitches.
6675 if (adev->adm_on_routing_change) {
6676 adev->adm_on_routing_change(adev->adm_data,
6677 in->capture_handle);
6678 ret = select_devices(adev, in->usecase);
6679 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6680 adev->adm_routing_changed = true;
6681 }
6682 }
6683 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006684 if (usb_addr)
6685 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006686 }
6687 pthread_mutex_unlock(&adev->lock);
6688 pthread_mutex_unlock(&in->lock);
6689
6690 ALOGD("%s: exit: status(%d)", __func__, ret);
6691 return ret;
6692}
6693
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006694static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6695{
6696 struct stream_in *in = (struct stream_in *)stream;
6697 struct audio_device *adev = in->dev;
6698 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006699 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006700 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006701
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306702 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006703 parms = str_parms_create_str(kvpairs);
6704
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306705 if (!parms)
6706 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006707 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006708 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006709
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006710 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6711 if (ret >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306712 strlcpy(in->profile, value, sizeof(in->profile));
6713 ALOGV("updating stream profile with value '%s'", in->profile);
6714 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6715 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006716 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306717 in->sample_rate, in->bit_width,
6718 in->profile, &in->app_type_cfg);
6719 }
6720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006721 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006722 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006723
6724 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306725error:
Eric Laurent994a6932013-07-17 11:51:42 -07006726 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006727 return ret;
6728}
6729
6730static char* in_get_parameters(const struct audio_stream *stream,
6731 const char *keys)
6732{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006733 struct stream_in *in = (struct stream_in *)stream;
6734 struct str_parms *query = str_parms_create_str(keys);
6735 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006736 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006737
6738 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006739 if (reply) {
6740 str_parms_destroy(reply);
6741 }
6742 if (query) {
6743 str_parms_destroy(query);
6744 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006745 ALOGE("in_get_parameters: failed to create query or reply");
6746 return NULL;
6747 }
6748
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006749 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006750
6751 voice_extn_in_get_parameters(in, query, reply);
6752
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006753 stream_get_parameter_channels(query, reply,
6754 &in->supported_channel_masks[0]);
6755 stream_get_parameter_formats(query, reply,
6756 &in->supported_formats[0]);
6757 stream_get_parameter_rates(query, reply,
6758 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006759 str = str_parms_to_str(reply);
6760 str_parms_destroy(query);
6761 str_parms_destroy(reply);
6762
6763 ALOGV("%s: exit: returns - %s", __func__, str);
6764 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006765}
6766
Aalique Grahame22e49102018-12-18 14:23:57 -08006767static int in_set_gain(struct audio_stream_in *stream,
6768 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006769{
Aalique Grahame22e49102018-12-18 14:23:57 -08006770 struct stream_in *in = (struct stream_in *)stream;
6771 char mixer_ctl_name[128];
6772 struct mixer_ctl *ctl;
6773 int ctl_value;
6774
6775 ALOGV("%s: gain %f", __func__, gain);
6776
6777 if (stream == NULL)
6778 return -EINVAL;
6779
6780 /* in_set_gain() only used to silence MMAP capture for now */
6781 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6782 return -ENOSYS;
6783
6784 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6785
6786 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6787 if (!ctl) {
6788 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6789 __func__, mixer_ctl_name);
6790 return -ENOSYS;
6791 }
6792
6793 if (gain < RECORD_GAIN_MIN)
6794 gain = RECORD_GAIN_MIN;
6795 else if (gain > RECORD_GAIN_MAX)
6796 gain = RECORD_GAIN_MAX;
6797 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6798
6799 mixer_ctl_set_value(ctl, 0, ctl_value);
6800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006801 return 0;
6802}
6803
6804static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6805 size_t bytes)
6806{
6807 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306808
6809 if (in == NULL) {
6810 ALOGE("%s: stream_in ptr is NULL", __func__);
6811 return -EINVAL;
6812 }
6813
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006814 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306815 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306816 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006817
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006818 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306819
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006820 if (in->is_st_session) {
6821 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6822 /* Read from sound trigger HAL */
6823 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006824 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006825 if (adev->num_va_sessions < UINT_MAX)
6826 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006827 in->standby = 0;
6828 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006829 pthread_mutex_unlock(&in->lock);
6830 return bytes;
6831 }
6832
Haynes Mathew George16081042017-05-31 17:16:49 -07006833 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6834 ret = -ENOSYS;
6835 goto exit;
6836 }
6837
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006838 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6839 !in->standby && adev->adm_routing_changed) {
6840 ret = -ENOSYS;
6841 goto exit;
6842 }
6843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006844 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006845 pthread_mutex_lock(&adev->lock);
6846 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6847 ret = voice_extn_compress_voip_start_input_stream(in);
6848 else
6849 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006850 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6851 if (adev->num_va_sessions < UINT_MAX)
6852 adev->num_va_sessions++;
6853 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006854 pthread_mutex_unlock(&adev->lock);
6855 if (ret != 0) {
6856 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006857 }
6858 in->standby = 0;
6859 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006860
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306861 /* Avoid read if capture_stopped is set */
6862 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6863 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6864 ret = -EINVAL;
6865 goto exit;
6866 }
6867
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006868 // what's the duration requested by the client?
6869 long ns = 0;
6870
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306871 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006872 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6873 in->config.rate;
6874
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006875 ret = request_in_focus(in, ns);
6876 if (ret != 0)
6877 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006878 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006879
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306880 if (audio_extn_cin_attached_usecase(in->usecase)) {
6881 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6882 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306883 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006884 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306885 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006886 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006887 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006888 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006889 } else if (audio_extn_ffv_get_stream() == in) {
6890 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306891 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006892 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306893 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6894 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6895 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6896 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306897 ret = -EINVAL;
6898 goto exit;
6899 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306900 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306901 ret = -errno;
6902 }
6903 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306904 /* bytes read is always set to bytes for non compress usecases */
6905 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006906 }
6907
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006908 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006910 /*
Quinn Malef6050362019-01-30 15:55:40 -08006911 * Instead of writing zeroes here, we could trust the hardware to always
6912 * provide zeroes when muted. This is also muted with voice recognition
6913 * usecases so that other clients do not have access to voice recognition
6914 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006915 */
Quinn Malef6050362019-01-30 15:55:40 -08006916 if ((ret == 0 && voice_get_mic_mute(adev) &&
6917 !voice_is_in_call_rec_stream(in) &&
6918 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6919 (adev->num_va_sessions &&
6920 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6921 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6922 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006923 memset(buffer, 0, bytes);
6924
6925exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306926 frame_size = audio_stream_in_frame_size(stream);
6927 if (frame_size > 0)
6928 in->frames_read += bytes_read/frame_size;
6929
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006930 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306931 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006932 pthread_mutex_unlock(&in->lock);
6933
6934 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306935 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306936 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306937 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306938 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306939 in->standby = true;
6940 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306941 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6942 bytes_read = bytes;
6943 memset(buffer, 0, bytes);
6944 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006945 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006946 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6947 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006948 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306949 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306950 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006951 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306952 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006953}
6954
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006955static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006956{
6957 return 0;
6958}
6959
Aalique Grahame22e49102018-12-18 14:23:57 -08006960static int in_get_capture_position(const struct audio_stream_in *stream,
6961 int64_t *frames, int64_t *time)
6962{
6963 if (stream == NULL || frames == NULL || time == NULL) {
6964 return -EINVAL;
6965 }
6966 struct stream_in *in = (struct stream_in *)stream;
6967 int ret = -ENOSYS;
6968
6969 lock_input_stream(in);
6970 // note: ST sessions do not close the alsa pcm driver synchronously
6971 // on standby. Therefore, we may return an error even though the
6972 // pcm stream is still opened.
6973 if (in->standby) {
6974 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6975 "%s stream in standby but pcm not NULL for non ST session", __func__);
6976 goto exit;
6977 }
6978 if (in->pcm) {
6979 struct timespec timestamp;
6980 unsigned int avail;
6981 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6982 *frames = in->frames_read + avail;
6983 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6984 ret = 0;
6985 }
6986 }
6987exit:
6988 pthread_mutex_unlock(&in->lock);
6989 return ret;
6990}
6991
Carter Hsu2e429db2019-05-14 18:50:52 +08006992static int in_update_effect_list(bool add, effect_handle_t effect,
6993 struct listnode *head)
6994{
6995 struct listnode *node;
6996 struct in_effect_list *elist = NULL;
6997 struct in_effect_list *target = NULL;
6998 int ret = 0;
6999
7000 if (!head)
7001 return ret;
7002
7003 list_for_each(node, head) {
7004 elist = node_to_item(node, struct in_effect_list, list);
7005 if (elist->handle == effect) {
7006 target = elist;
7007 break;
7008 }
7009 }
7010
7011 if (add) {
7012 if (target) {
7013 ALOGD("effect %p already exist", effect);
7014 return ret;
7015 }
7016
7017 target = (struct in_effect_list *)
7018 calloc(1, sizeof(struct in_effect_list));
7019
7020 if (!target) {
7021 ALOGE("%s:fail to allocate memory", __func__);
7022 return -ENOMEM;
7023 }
7024
7025 target->handle = effect;
7026 list_add_tail(head, &target->list);
7027 } else {
7028 if (target) {
7029 list_remove(&target->list);
7030 free(target);
7031 }
7032 }
7033
7034 return ret;
7035}
7036
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007037static int add_remove_audio_effect(const struct audio_stream *stream,
7038 effect_handle_t effect,
7039 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007040{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007041 struct stream_in *in = (struct stream_in *)stream;
7042 int status = 0;
7043 effect_descriptor_t desc;
7044
7045 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007046 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7047
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007048 if (status != 0)
7049 return status;
7050
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007051 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007052 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007053 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007054 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7055 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007056 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007057
7058 in_update_effect_list(enable, effect, &in->aec_list);
7059 enable = !list_empty(&in->aec_list);
7060 if (enable == in->enable_aec)
7061 goto exit;
7062
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007063 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007064 ALOGD("AEC enable %d", enable);
7065
Aalique Grahame22e49102018-12-18 14:23:57 -08007066 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7067 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7068 in->dev->enable_voicerx = enable;
7069 struct audio_usecase *usecase;
7070 struct listnode *node;
7071 list_for_each(node, &in->dev->usecase_list) {
7072 usecase = node_to_item(node, struct audio_usecase, list);
7073 if (usecase->type == PCM_PLAYBACK)
7074 select_devices(in->dev, usecase->id);
7075 }
7076 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007077 if (!in->standby) {
7078 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7079 select_devices(in->dev, in->usecase);
7080 }
7081
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007082 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007083 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7084
7085 in_update_effect_list(enable, effect, &in->ns_list);
7086 enable = !list_empty(&in->ns_list);
7087 if (enable == in->enable_ns)
7088 goto exit;
7089
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007090 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007091 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007092 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007093 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7094 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007095 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7096 select_devices(in->dev, in->usecase);
7097 } else
7098 select_devices(in->dev, in->usecase);
7099 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007100 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007101exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007102 pthread_mutex_unlock(&in->dev->lock);
7103 pthread_mutex_unlock(&in->lock);
7104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007105 return 0;
7106}
7107
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007108static int in_add_audio_effect(const struct audio_stream *stream,
7109 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007110{
Eric Laurent994a6932013-07-17 11:51:42 -07007111 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007112 return add_remove_audio_effect(stream, effect, true);
7113}
7114
7115static int in_remove_audio_effect(const struct audio_stream *stream,
7116 effect_handle_t effect)
7117{
Eric Laurent994a6932013-07-17 11:51:42 -07007118 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007119 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007120}
7121
Derek Chenf939fb72018-11-13 13:34:41 -08007122streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7123 audio_io_handle_t input)
7124{
7125 struct listnode *node;
7126
7127 list_for_each(node, &dev->active_inputs_list) {
7128 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7129 streams_input_ctxt_t,
7130 list);
7131 if (in_ctxt->input->capture_handle == input) {
7132 return in_ctxt;
7133 }
7134 }
7135 return NULL;
7136}
7137
7138streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7139 audio_io_handle_t output)
7140{
7141 struct listnode *node;
7142
7143 list_for_each(node, &dev->active_outputs_list) {
7144 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7145 streams_output_ctxt_t,
7146 list);
7147 if (out_ctxt->output->handle == output) {
7148 return out_ctxt;
7149 }
7150 }
7151 return NULL;
7152}
7153
Haynes Mathew George16081042017-05-31 17:16:49 -07007154static int in_stop(const struct audio_stream_in* stream)
7155{
7156 struct stream_in *in = (struct stream_in *)stream;
7157 struct audio_device *adev = in->dev;
7158
7159 int ret = -ENOSYS;
7160 ALOGV("%s", __func__);
7161 pthread_mutex_lock(&adev->lock);
7162 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7163 in->capture_started && in->pcm != NULL) {
7164 pcm_stop(in->pcm);
7165 ret = stop_input_stream(in);
7166 in->capture_started = false;
7167 }
7168 pthread_mutex_unlock(&adev->lock);
7169 return ret;
7170}
7171
7172static int in_start(const struct audio_stream_in* stream)
7173{
7174 struct stream_in *in = (struct stream_in *)stream;
7175 struct audio_device *adev = in->dev;
7176 int ret = -ENOSYS;
7177
7178 ALOGV("%s in %p", __func__, in);
7179 pthread_mutex_lock(&adev->lock);
7180 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7181 !in->capture_started && in->pcm != NULL) {
7182 if (!in->capture_started) {
7183 ret = start_input_stream(in);
7184 if (ret == 0) {
7185 in->capture_started = true;
7186 }
7187 }
7188 }
7189 pthread_mutex_unlock(&adev->lock);
7190 return ret;
7191}
7192
Phil Burke0a86d12019-02-16 22:28:11 -08007193// Read offset for the positional timestamp from a persistent vendor property.
7194// This is to workaround apparent inaccuracies in the timing information that
7195// is used by the AAudio timing model. The inaccuracies can cause glitches.
7196static int64_t in_get_mmap_time_offset() {
7197 const int32_t kDefaultOffsetMicros = 0;
7198 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007199 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007200 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7201 return mmap_time_offset_micros * (int64_t)1000;
7202}
7203
Haynes Mathew George16081042017-05-31 17:16:49 -07007204static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7205 int32_t min_size_frames,
7206 struct audio_mmap_buffer_info *info)
7207{
7208 struct stream_in *in = (struct stream_in *)stream;
7209 struct audio_device *adev = in->dev;
7210 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007211 unsigned int offset1 = 0;
7212 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007213 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007214 uint32_t mmap_size = 0;
7215 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007216
7217 pthread_mutex_lock(&adev->lock);
7218 ALOGV("%s in %p", __func__, in);
7219
Sharad Sanglec6f32552018-05-04 16:15:38 +05307220 if (CARD_STATUS_OFFLINE == in->card_status||
7221 CARD_STATUS_OFFLINE == adev->card_status) {
7222 ALOGW("in->card_status or adev->card_status offline, try again");
7223 ret = -EIO;
7224 goto exit;
7225 }
7226
Haynes Mathew George16081042017-05-31 17:16:49 -07007227 if (info == NULL || min_size_frames == 0) {
7228 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7229 ret = -EINVAL;
7230 goto exit;
7231 }
7232 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7233 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7234 ALOGV("%s in %p", __func__, in);
7235 ret = -ENOSYS;
7236 goto exit;
7237 }
7238 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7239 if (in->pcm_device_id < 0) {
7240 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7241 __func__, in->pcm_device_id, in->usecase);
7242 ret = -EINVAL;
7243 goto exit;
7244 }
7245
7246 adjust_mmap_period_count(&in->config, min_size_frames);
7247
7248 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7249 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7250 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7251 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307252 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307253 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7254 in->card_status = CARD_STATUS_OFFLINE;
7255 adev->card_status = CARD_STATUS_OFFLINE;
7256 ret = -EIO;
7257 goto exit;
7258 }
7259
Haynes Mathew George16081042017-05-31 17:16:49 -07007260 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7261 step = "open";
7262 ret = -ENODEV;
7263 goto exit;
7264 }
7265
7266 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7267 if (ret < 0) {
7268 step = "begin";
7269 goto exit;
7270 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007271
Arun Mirpuri5d170872019-03-26 13:21:31 -07007272 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7273 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7274 info->burst_size_frames = in->config.period_size;
7275 ret = platform_get_mmap_data_fd(adev->platform,
7276 in->pcm_device_id, 1 /*capture*/,
7277 &info->shared_memory_fd,
7278 &mmap_size);
7279 if (ret < 0) {
7280 // Fall back to non exclusive mode
7281 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7282 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007283 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7284 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7285
Arun Mirpuri5d170872019-03-26 13:21:31 -07007286 if (mmap_size < buffer_size) {
7287 step = "mmap";
7288 goto exit;
7289 }
7290 // FIXME: indicate exclusive mode support by returning a negative buffer size
7291 info->buffer_size_frames *= -1;
7292 }
7293
7294 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007295
7296 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7297 if (ret < 0) {
7298 step = "commit";
7299 goto exit;
7300 }
7301
Phil Burke0a86d12019-02-16 22:28:11 -08007302 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7303
Haynes Mathew George16081042017-05-31 17:16:49 -07007304 in->standby = false;
7305 ret = 0;
7306
7307 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7308 __func__, info->shared_memory_address, info->buffer_size_frames);
7309
7310exit:
7311 if (ret != 0) {
7312 if (in->pcm == NULL) {
7313 ALOGE("%s: %s - %d", __func__, step, ret);
7314 } else {
7315 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7316 pcm_close(in->pcm);
7317 in->pcm = NULL;
7318 }
7319 }
7320 pthread_mutex_unlock(&adev->lock);
7321 return ret;
7322}
7323
7324static int in_get_mmap_position(const struct audio_stream_in *stream,
7325 struct audio_mmap_position *position)
7326{
7327 struct stream_in *in = (struct stream_in *)stream;
7328 ALOGVV("%s", __func__);
7329 if (position == NULL) {
7330 return -EINVAL;
7331 }
7332 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7333 return -ENOSYS;
7334 }
7335 if (in->pcm == NULL) {
7336 return -ENOSYS;
7337 }
7338 struct timespec ts = { 0, 0 };
7339 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7340 if (ret < 0) {
7341 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7342 return ret;
7343 }
Phil Burke0a86d12019-02-16 22:28:11 -08007344 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7345 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007346 return 0;
7347}
7348
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307349static int in_get_active_microphones(const struct audio_stream_in *stream,
7350 struct audio_microphone_characteristic_t *mic_array,
7351 size_t *mic_count) {
7352 struct stream_in *in = (struct stream_in *)stream;
7353 struct audio_device *adev = in->dev;
7354 ALOGVV("%s", __func__);
7355
7356 lock_input_stream(in);
7357 pthread_mutex_lock(&adev->lock);
7358 int ret = platform_get_active_microphones(adev->platform,
7359 audio_channel_count_from_in_mask(in->channel_mask),
7360 in->usecase, mic_array, mic_count);
7361 pthread_mutex_unlock(&adev->lock);
7362 pthread_mutex_unlock(&in->lock);
7363
7364 return ret;
7365}
7366
7367static int adev_get_microphones(const struct audio_hw_device *dev,
7368 struct audio_microphone_characteristic_t *mic_array,
7369 size_t *mic_count) {
7370 struct audio_device *adev = (struct audio_device *)dev;
7371 ALOGVV("%s", __func__);
7372
7373 pthread_mutex_lock(&adev->lock);
7374 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7375 pthread_mutex_unlock(&adev->lock);
7376
7377 return ret;
7378}
juyuchendb308c22019-01-21 11:57:17 -07007379
7380static void in_update_sink_metadata(struct audio_stream_in *stream,
7381 const struct sink_metadata *sink_metadata) {
7382
7383 if (stream == NULL
7384 || sink_metadata == NULL
7385 || sink_metadata->tracks == NULL) {
7386 return;
7387 }
7388
7389 int error = 0;
7390 struct stream_in *in = (struct stream_in *)stream;
7391 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007392 struct listnode devices;
7393
7394 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007395
7396 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007397 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007398
7399 lock_input_stream(in);
7400 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007401 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007402
7403 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007404 && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007405 && adev->voice_tx_output != NULL) {
7406 /* Use the rx device from afe-proxy record to route voice call because
7407 there is no routing if tx device is on primary hal and rx device
7408 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007409 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007410
7411 if (!voice_is_call_state_active(adev)) {
7412 if (adev->mode == AUDIO_MODE_IN_CALL) {
7413 adev->current_call_output = adev->voice_tx_output;
7414 error = voice_start_call(adev);
7415 if (error != 0)
7416 ALOGE("%s: start voice call failed %d", __func__, error);
7417 }
7418 } else {
7419 adev->current_call_output = adev->voice_tx_output;
7420 voice_update_devices_for_all_voice_usecases(adev);
7421 }
7422 }
7423
7424 pthread_mutex_unlock(&adev->lock);
7425 pthread_mutex_unlock(&in->lock);
7426}
7427
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307428int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007429 audio_io_handle_t handle,
7430 audio_devices_t devices,
7431 audio_output_flags_t flags,
7432 struct audio_config *config,
7433 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007434 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007435{
7436 struct audio_device *adev = (struct audio_device *)dev;
7437 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307438 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007439 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007440 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307441 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007442 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7443 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7444 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7445 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007446 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007447 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7448 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007449 bool force_haptic_path =
7450 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007451 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007452
kunleizdff872d2018-08-20 14:40:33 +08007453 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007454 is_usb_dev = false;
7455 devices = AUDIO_DEVICE_OUT_SPEAKER;
7456 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7457 __func__, devices);
7458 }
7459
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007460 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307461
Rahul Sharma99770982019-03-06 17:05:26 +05307462 pthread_mutex_lock(&adev->lock);
7463 if (out_get_stream(adev, handle) != NULL) {
7464 ALOGW("%s, output stream already opened", __func__);
7465 ret = -EEXIST;
7466 }
7467 pthread_mutex_unlock(&adev->lock);
7468 if (ret)
7469 return ret;
7470
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007471 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7472
Mingming Yin3a941d42016-02-17 18:08:05 -08007473 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007474 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7475 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307476
7477
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007478 if (!out) {
7479 return -ENOMEM;
7480 }
7481
Haynes Mathew George204045b2015-02-25 20:32:03 -08007482 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007483 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307484 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007485 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007486 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007488 if (devices == AUDIO_DEVICE_NONE)
7489 devices = AUDIO_DEVICE_OUT_SPEAKER;
7490
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007491 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007492 list_init(&out->device_list);
7493 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007494 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007495 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007496 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307497 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307498 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7499 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7500 else
7501 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007502 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007503 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007504 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307505 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307506 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307507 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007508 out->hal_output_suspend_supported = 0;
7509 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307510 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307511 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307512 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007513 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007514
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307515 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307516 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007517 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7518
Aalique Grahame22e49102018-12-18 14:23:57 -08007519 if (direct_dev &&
7520 (audio_is_linear_pcm(out->format) ||
7521 config->format == AUDIO_FORMAT_DEFAULT) &&
7522 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7523 audio_format_t req_format = config->format;
7524 audio_channel_mask_t req_channel_mask = config->channel_mask;
7525 uint32_t req_sample_rate = config->sample_rate;
7526
7527 pthread_mutex_lock(&adev->lock);
7528 if (is_hdmi) {
7529 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7530 ret = read_hdmi_sink_caps(out);
7531 if (config->sample_rate == 0)
7532 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7533 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7534 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7535 if (config->format == AUDIO_FORMAT_DEFAULT)
7536 config->format = AUDIO_FORMAT_PCM_16_BIT;
7537 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007538 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7539 &config->format,
7540 &out->supported_formats[0],
7541 MAX_SUPPORTED_FORMATS,
7542 &config->channel_mask,
7543 &out->supported_channel_masks[0],
7544 MAX_SUPPORTED_CHANNEL_MASKS,
7545 &config->sample_rate,
7546 &out->supported_sample_rates[0],
7547 MAX_SUPPORTED_SAMPLE_RATES);
7548 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007549 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007550
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007551 pthread_mutex_unlock(&adev->lock);
7552 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007553 if (ret == -ENOSYS) {
7554 /* ignore and go with default */
7555 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007556 }
7557 // For MMAP NO IRQ, allow conversions in ADSP
7558 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7559 goto error_open;
7560 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007561 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007562 goto error_open;
7563 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007564
7565 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7566 config->sample_rate = req_sample_rate;
7567 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7568 config->channel_mask = req_channel_mask;
7569 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7570 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007571 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007572
7573 out->sample_rate = config->sample_rate;
7574 out->channel_mask = config->channel_mask;
7575 out->format = config->format;
7576 if (is_hdmi) {
7577 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7578 out->config = pcm_config_hdmi_multi;
7579 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7580 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7581 out->config = pcm_config_mmap_playback;
7582 out->stream.start = out_start;
7583 out->stream.stop = out_stop;
7584 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7585 out->stream.get_mmap_position = out_get_mmap_position;
7586 } else {
7587 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7588 out->config = pcm_config_hifi;
7589 }
7590
7591 out->config.rate = out->sample_rate;
7592 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7593 if (is_hdmi) {
7594 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7595 audio_bytes_per_sample(out->format));
7596 }
7597 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007598 }
7599
Derek Chenf6318be2017-06-12 17:16:24 -04007600 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007601 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007602 /* extract car audio stream index */
7603 out->car_audio_stream =
7604 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7605 if (out->car_audio_stream < 0) {
7606 ALOGE("%s: invalid car audio stream %x",
7607 __func__, out->car_audio_stream);
7608 ret = -EINVAL;
7609 goto error_open;
7610 }
7611 /* save car audio stream and address for bus device */
7612 strlcpy(out->address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
7613 ALOGV("%s: address %s, car_audio_stream %x",
7614 __func__, out->address, out->car_audio_stream);
7615 }
7616
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007617 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007618 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007619 if (!voice_extn_is_compress_voip_supported()) {
7620 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7621 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007622 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7623 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007624 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7625 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007626 out->volume_l = INVALID_OUT_VOLUME;
7627 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007628
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007629 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007630 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007631 uint32_t channel_count =
7632 audio_channel_count_from_out_mask(out->channel_mask);
7633 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7634 out->sample_rate, out->format,
7635 channel_count, false);
7636 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7637 if (frame_size != 0)
7638 out->config.period_size = buffer_size / frame_size;
7639 else
7640 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007641 }
7642 } else {
7643 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7644 voice_extn_compress_voip_is_active(out->dev)) &&
7645 (voice_extn_compress_voip_is_config_supported(config))) {
7646 ret = voice_extn_compress_voip_open_output_stream(out);
7647 if (ret != 0) {
7648 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7649 __func__, ret);
7650 goto error_open;
7651 }
Sujin Panicker19027262019-09-16 18:28:06 +05307652 } else {
7653 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7654 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007655 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007656 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007657 } else if (audio_is_linear_pcm(out->format) &&
7658 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7659 out->channel_mask = config->channel_mask;
7660 out->sample_rate = config->sample_rate;
7661 out->format = config->format;
7662 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7663 // does this change?
7664 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7665 out->config.rate = config->sample_rate;
7666 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7667 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7668 audio_bytes_per_sample(config->format));
7669 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007670 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307671 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307672 pthread_mutex_lock(&adev->lock);
7673 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7674 pthread_mutex_unlock(&adev->lock);
7675
7676 // reject offload during card offline to allow
7677 // fallback to s/w paths
7678 if (offline) {
7679 ret = -ENODEV;
7680 goto error_open;
7681 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007682
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007683 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7684 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7685 ALOGE("%s: Unsupported Offload information", __func__);
7686 ret = -EINVAL;
7687 goto error_open;
7688 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007689
Atul Khare3fa6e542017-08-09 00:56:17 +05307690 if (config->offload_info.format == 0)
7691 config->offload_info.format = config->format;
7692 if (config->offload_info.sample_rate == 0)
7693 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007694
Mingming Yin90310102013-11-13 16:57:00 -08007695 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307696 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007697 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007698 ret = -EINVAL;
7699 goto error_open;
7700 }
7701
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007702 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7703 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7704 (audio_extn_passthru_is_passthrough_stream(out)) &&
7705 !((config->sample_rate == 48000) ||
7706 (config->sample_rate == 96000) ||
7707 (config->sample_rate == 192000))) {
7708 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7709 __func__, config->sample_rate, config->offload_info.format);
7710 ret = -EINVAL;
7711 goto error_open;
7712 }
7713
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007714 out->compr_config.codec = (struct snd_codec *)
7715 calloc(1, sizeof(struct snd_codec));
7716
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007717 if (!out->compr_config.codec) {
7718 ret = -ENOMEM;
7719 goto error_open;
7720 }
7721
Dhananjay Kumarac341582017-02-23 23:42:25 +05307722 out->stream.pause = out_pause;
7723 out->stream.resume = out_resume;
7724 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307725 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307726 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007727 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307728 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007729 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307730 } else {
7731 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7732 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007733 }
vivek mehta446c3962015-09-14 10:57:35 -07007734
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307735 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7736 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007737#ifdef AUDIO_GKI_ENABLED
7738 /* out->compr_config.codec->reserved[1] is for flags */
7739 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7740#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307741 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007742#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307743 }
7744
vivek mehta446c3962015-09-14 10:57:35 -07007745 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007746 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007747 config->format == 0 && config->sample_rate == 0 &&
7748 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007749 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007750 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7751 } else {
7752 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7753 ret = -EEXIST;
7754 goto error_open;
7755 }
vivek mehta446c3962015-09-14 10:57:35 -07007756 }
7757
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007758 if (config->offload_info.channel_mask)
7759 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007760 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007761 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007762 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007763 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307764 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007765 ret = -EINVAL;
7766 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007767 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007768
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007769 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007770 out->sample_rate = config->offload_info.sample_rate;
7771
Mingming Yin3ee55c62014-08-04 14:23:35 -07007772 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007773
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307774 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307775 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307776 audio_extn_dolby_send_ddp_endp_params(adev);
7777 audio_extn_dolby_set_dmid(adev);
7778 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007779
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007780 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007781 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007782 out->compr_config.codec->bit_rate =
7783 config->offload_info.bit_rate;
7784 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307785 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007786 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307787 /* Update bit width only for non passthrough usecases.
7788 * For passthrough usecases, the output will always be opened @16 bit
7789 */
7790 if (!audio_extn_passthru_is_passthrough_stream(out))
7791 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307792
7793 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007794#ifdef AUDIO_GKI_ENABLED
7795 /* out->compr_config.codec->reserved[1] is for flags */
7796 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7797 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7798#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307799 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7800 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007801#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307802
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007803 /*TODO: Do we need to change it for passthrough */
7804 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007805
Manish Dewangana6fc5442015-08-24 20:30:31 +05307806 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7807 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307808 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307809 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307810 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7811 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307812
7813 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7814 AUDIO_FORMAT_PCM) {
7815
7816 /*Based on platform support, configure appropriate alsa format for corresponding
7817 *hal input format.
7818 */
7819 out->compr_config.codec->format = hal_format_to_alsa(
7820 config->offload_info.format);
7821
Ashish Jain83a6cc22016-06-28 14:34:17 +05307822 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307823 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307824 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307825
Dhananjay Kumarac341582017-02-23 23:42:25 +05307826 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307827 *hal input format and alsa format might differ based on platform support.
7828 */
7829 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307830 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307831
7832 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7833
Deeraj Soman93155a62019-09-30 19:00:37 +05307834 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7835 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7836 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7837 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7838 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307839
Ashish Jainf1eaa582016-05-23 20:54:24 +05307840 /* Check if alsa session is configured with the same format as HAL input format,
7841 * if not then derive correct fragment size needed to accomodate the
7842 * conversion of HAL input format to alsa format.
7843 */
7844 audio_extn_utils_update_direct_pcm_fragment_size(out);
7845
7846 /*if hal input and output fragment size is different this indicates HAL input format is
7847 *not same as the alsa format
7848 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307849 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307850 /*Allocate a buffer to convert input data to the alsa configured format.
7851 *size of convert buffer is equal to the size required to hold one fragment size
7852 *worth of pcm data, this is because flinger does not write more than fragment_size
7853 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307854 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7855 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307856 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7857 ret = -ENOMEM;
7858 goto error_open;
7859 }
7860 }
7861 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7862 out->compr_config.fragment_size =
7863 audio_extn_passthru_get_buffer_size(&config->offload_info);
7864 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7865 } else {
7866 out->compr_config.fragment_size =
7867 platform_get_compress_offload_buffer_size(&config->offload_info);
7868 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7869 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007870
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307871 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7872 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7873 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007874 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307875 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007876
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307877 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7878 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7879 }
7880
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007881 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7882 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007883
Manish Dewangan69426c82017-01-30 17:35:36 +05307884 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7885 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7886 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7887 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7888 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7889 } else {
7890 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7891 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007892
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307893 memset(&out->channel_map_param, 0,
7894 sizeof(struct audio_out_channel_map_param));
7895
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007896 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307897 out->send_next_track_params = false;
7898 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007899 out->offload_state = OFFLOAD_STATE_IDLE;
7900 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007901 out->writeAt.tv_sec = 0;
7902 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007903
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007904 audio_extn_dts_create_state_notifier_node(out->usecase);
7905
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007906 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7907 __func__, config->offload_info.version,
7908 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307909
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307910 /* Check if DSD audio format is supported in codec
7911 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307912 */
7913
7914 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307915 (!platform_check_codec_dsd_support(adev->platform) ||
7916 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307917 ret = -EINVAL;
7918 goto error_open;
7919 }
7920
Ashish Jain5106d362016-05-11 19:23:33 +05307921 /* Disable gapless if any of the following is true
7922 * passthrough playback
7923 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307924 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307925 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307926 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307927 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007928 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307929 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307930 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307931 check_and_set_gapless_mode(adev, false);
7932 } else
7933 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007934
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307935 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007936 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7937 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307938 if (config->format == AUDIO_FORMAT_DSD) {
7939 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08007940#ifdef AUDIO_GKI_ENABLED
7941 /* out->compr_config.codec->reserved[0] is for compr_passthr */
7942 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
7943#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307944 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08007945#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307946 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007947
7948 create_offload_callback_thread(out);
7949
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007950 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007951 switch (config->sample_rate) {
7952 case 0:
7953 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7954 break;
7955 case 8000:
7956 case 16000:
7957 case 48000:
7958 out->sample_rate = config->sample_rate;
7959 break;
7960 default:
7961 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7962 config->sample_rate);
7963 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7964 ret = -EINVAL;
7965 goto error_open;
7966 }
7967 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7968 switch (config->channel_mask) {
7969 case AUDIO_CHANNEL_NONE:
7970 case AUDIO_CHANNEL_OUT_STEREO:
7971 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7972 break;
7973 default:
7974 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7975 config->channel_mask);
7976 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7977 ret = -EINVAL;
7978 goto error_open;
7979 }
7980 switch (config->format) {
7981 case AUDIO_FORMAT_DEFAULT:
7982 case AUDIO_FORMAT_PCM_16_BIT:
7983 out->format = AUDIO_FORMAT_PCM_16_BIT;
7984 break;
7985 default:
7986 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7987 config->format);
7988 config->format = AUDIO_FORMAT_PCM_16_BIT;
7989 ret = -EINVAL;
7990 goto error_open;
7991 }
7992
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307993 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007994 if (ret != 0) {
7995 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007996 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007997 goto error_open;
7998 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007999 } else if (is_single_device_type_equal(&out->device_list,
8000 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008001 switch (config->sample_rate) {
8002 case 0:
8003 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8004 break;
8005 case 8000:
8006 case 16000:
8007 case 48000:
8008 out->sample_rate = config->sample_rate;
8009 break;
8010 default:
8011 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8012 config->sample_rate);
8013 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8014 ret = -EINVAL;
8015 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008016 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008017 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8018 switch (config->channel_mask) {
8019 case AUDIO_CHANNEL_NONE:
8020 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8021 break;
8022 case AUDIO_CHANNEL_OUT_STEREO:
8023 out->channel_mask = config->channel_mask;
8024 break;
8025 default:
8026 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8027 config->channel_mask);
8028 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8029 ret = -EINVAL;
8030 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008031 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008032 switch (config->format) {
8033 case AUDIO_FORMAT_DEFAULT:
8034 out->format = AUDIO_FORMAT_PCM_16_BIT;
8035 break;
8036 case AUDIO_FORMAT_PCM_16_BIT:
8037 out->format = config->format;
8038 break;
8039 default:
8040 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8041 config->format);
8042 config->format = AUDIO_FORMAT_PCM_16_BIT;
8043 ret = -EINVAL;
8044 break;
8045 }
8046 if (ret != 0)
8047 goto error_open;
8048
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008049 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8050 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008051 out->config.rate = out->sample_rate;
8052 out->config.channels =
8053 audio_channel_count_from_out_mask(out->channel_mask);
8054 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008055 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008056 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308057 unsigned int channels = 0;
8058 /*Update config params to default if not set by the caller*/
8059 if (config->sample_rate == 0)
8060 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8061 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8062 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8063 if (config->format == AUDIO_FORMAT_DEFAULT)
8064 config->format = AUDIO_FORMAT_PCM_16_BIT;
8065
8066 channels = audio_channel_count_from_out_mask(out->channel_mask);
8067
Varun Balaraje49253e2017-07-06 19:48:56 +05308068 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8069 out->usecase = get_interactive_usecase(adev);
8070 out->config = pcm_config_low_latency;
8071 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308072 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008073 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8074 out->flags);
8075 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008076 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8077 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8078 out->config = pcm_config_mmap_playback;
8079 out->stream.start = out_start;
8080 out->stream.stop = out_stop;
8081 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8082 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308083 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8084 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008085 out->hal_output_suspend_supported =
8086 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8087 out->dynamic_pm_qos_config_supported =
8088 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8089 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008090 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8091 } else {
8092 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8093 //the mixer path will be a string similar to "low-latency-playback resume"
8094 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8095 strlcat(out->pm_qos_mixer_path,
8096 " resume", MAX_MIXER_PATH_LEN);
8097 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8098 out->pm_qos_mixer_path);
8099 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308100 out->config = pcm_config_low_latency;
8101 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8102 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8103 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308104 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8105 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8106 if (out->config.period_size <= 0) {
8107 ALOGE("Invalid configuration period size is not valid");
8108 ret = -EINVAL;
8109 goto error_open;
8110 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008111 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8112 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8113 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008114 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8115 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8116 out->config = pcm_config_haptics_audio;
8117 if (force_haptic_path)
8118 adev->haptics_config = pcm_config_haptics_audio;
8119 else
8120 adev->haptics_config = pcm_config_haptics;
8121
8122 out->config.channels =
8123 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8124
8125 if (force_haptic_path) {
8126 out->config.channels = 1;
8127 adev->haptics_config.channels = 1;
8128 } else
8129 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 -08008130 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008131 ret = audio_extn_auto_hal_open_output_stream(out);
8132 if (ret) {
8133 ALOGE("%s: Failed to open output stream for bus device", __func__);
8134 ret = -EINVAL;
8135 goto error_open;
8136 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308137 } else {
8138 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008139 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8140 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308141 }
8142 out->hal_ip_format = format = out->format;
8143 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8144 out->hal_op_format = pcm_format_to_hal(out->config.format);
8145 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8146 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008147 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308148 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308149 if (out->hal_ip_format != out->hal_op_format) {
8150 uint32_t buffer_size = out->config.period_size *
8151 format_to_bitwidth_table[out->hal_op_format] *
8152 out->config.channels;
8153 out->convert_buffer = calloc(1, buffer_size);
8154 if (out->convert_buffer == NULL){
8155 ALOGE("Allocation failed for convert buffer for size %d",
8156 out->compr_config.fragment_size);
8157 ret = -ENOMEM;
8158 goto error_open;
8159 }
8160 ALOGD("Convert buffer allocated of size %d", buffer_size);
8161 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008162 }
8163
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008164 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8165 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308166
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008167 /* TODO remove this hardcoding and check why width is zero*/
8168 if (out->bit_width == 0)
8169 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308170 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008171 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008172 &out->device_list, out->flags,
8173 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308174 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308175 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008176 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008177 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8178 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008179 if(adev->primary_output == NULL)
8180 adev->primary_output = out;
8181 else {
8182 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008183 ret = -EEXIST;
8184 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008185 }
8186 }
8187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008188 /* Check if this usecase is already existing */
8189 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008190 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8191 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008192 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008193 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008194 ret = -EEXIST;
8195 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008196 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008198 pthread_mutex_unlock(&adev->lock);
8199
8200 out->stream.common.get_sample_rate = out_get_sample_rate;
8201 out->stream.common.set_sample_rate = out_set_sample_rate;
8202 out->stream.common.get_buffer_size = out_get_buffer_size;
8203 out->stream.common.get_channels = out_get_channels;
8204 out->stream.common.get_format = out_get_format;
8205 out->stream.common.set_format = out_set_format;
8206 out->stream.common.standby = out_standby;
8207 out->stream.common.dump = out_dump;
8208 out->stream.common.set_parameters = out_set_parameters;
8209 out->stream.common.get_parameters = out_get_parameters;
8210 out->stream.common.add_audio_effect = out_add_audio_effect;
8211 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8212 out->stream.get_latency = out_get_latency;
8213 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008214#ifdef NO_AUDIO_OUT
8215 out->stream.write = out_write_for_no_output;
8216#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008217 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008218#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008219 out->stream.get_render_position = out_get_render_position;
8220 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008221 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008222
Haynes Mathew George16081042017-05-31 17:16:49 -07008223 if (out->realtime)
8224 out->af_period_multiplier = af_period_multiplier;
8225 else
8226 out->af_period_multiplier = 1;
8227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008228 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008229 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008230 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008231
8232 config->format = out->stream.common.get_format(&out->stream.common);
8233 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8234 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308235 register_format(out->format, out->supported_formats);
8236 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8237 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008238
Aalique Grahame22e49102018-12-18 14:23:57 -08008239 out->error_log = error_log_create(
8240 ERROR_LOG_ENTRIES,
8241 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8242
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308243 /*
8244 By locking output stream before registering, we allow the callback
8245 to update stream's state only after stream's initial state is set to
8246 adev state.
8247 */
8248 lock_output_stream(out);
8249 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8250 pthread_mutex_lock(&adev->lock);
8251 out->card_status = adev->card_status;
8252 pthread_mutex_unlock(&adev->lock);
8253 pthread_mutex_unlock(&out->lock);
8254
Aalique Grahame22e49102018-12-18 14:23:57 -08008255 stream_app_type_cfg_init(&out->app_type_cfg);
8256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008257 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308258 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008259 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008260
8261 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8262 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8263 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008264 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308265 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008266 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008267 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308268 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8269 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008270 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8271 out->usecase, PCM_PLAYBACK);
8272 hdlr_stream_cfg.flags = out->flags;
8273 hdlr_stream_cfg.type = PCM_PLAYBACK;
8274 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8275 &hdlr_stream_cfg);
8276 if (ret) {
8277 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8278 out->adsp_hdlr_stream_handle = NULL;
8279 }
8280 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308281 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8282 is_direct_passthough, false);
8283 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8284 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008285 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008286 if (ret < 0) {
8287 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8288 out->ip_hdlr_handle = NULL;
8289 }
8290 }
Derek Chenf939fb72018-11-13 13:34:41 -08008291
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008292 ret = io_streams_map_insert(adev, &out->stream.common,
8293 out->handle, AUDIO_PATCH_HANDLE_NONE);
8294 if (ret != 0)
8295 goto error_open;
8296
Derek Chenf939fb72018-11-13 13:34:41 -08008297 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8298 calloc(1, sizeof(streams_output_ctxt_t));
8299 if (out_ctxt == NULL) {
8300 ALOGE("%s fail to allocate output ctxt", __func__);
8301 ret = -ENOMEM;
8302 goto error_open;
8303 }
8304 out_ctxt->output = out;
8305
8306 pthread_mutex_lock(&adev->lock);
8307 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8308 pthread_mutex_unlock(&adev->lock);
8309
Eric Laurent994a6932013-07-17 11:51:42 -07008310 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008311 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008312
8313error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308314 if (out->convert_buffer)
8315 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008316 free(out);
8317 *stream_out = NULL;
8318 ALOGD("%s: exit: ret %d", __func__, ret);
8319 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008320}
8321
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308322void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008323 struct audio_stream_out *stream)
8324{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008325 struct stream_out *out = (struct stream_out *)stream;
8326 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008327 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008328
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008329 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308330
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008331 io_streams_map_remove(adev, out->handle);
8332
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308333 // must deregister from sndmonitor first to prevent races
8334 // between the callback and close_stream
8335 audio_extn_snd_mon_unregister_listener(out);
8336
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008337 /* close adsp hdrl session before standby */
8338 if (out->adsp_hdlr_stream_handle) {
8339 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8340 if (ret)
8341 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8342 out->adsp_hdlr_stream_handle = NULL;
8343 }
8344
Manish Dewangan21a850a2017-08-14 12:03:55 +05308345 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008346 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8347 out->ip_hdlr_handle = NULL;
8348 }
8349
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008350 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308351 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008352 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308353 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308354 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008355 if(ret != 0)
8356 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8357 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008358 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008359 out_standby(&stream->common);
8360
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008361 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008362 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008363 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008364 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008365 if (out->compr_config.codec != NULL)
8366 free(out->compr_config.codec);
8367 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008368
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308369 out->a2dp_compress_mute = false;
8370
Varun Balaraje49253e2017-07-06 19:48:56 +05308371 if (is_interactive_usecase(out->usecase))
8372 free_interactive_usecase(adev, out->usecase);
8373
Ashish Jain83a6cc22016-06-28 14:34:17 +05308374 if (out->convert_buffer != NULL) {
8375 free(out->convert_buffer);
8376 out->convert_buffer = NULL;
8377 }
8378
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008379 if (adev->voice_tx_output == out)
8380 adev->voice_tx_output = NULL;
8381
Aalique Grahame22e49102018-12-18 14:23:57 -08008382 error_log_destroy(out->error_log);
8383 out->error_log = NULL;
8384
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308385 if (adev->primary_output == out)
8386 adev->primary_output = NULL;
8387
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008388 pthread_cond_destroy(&out->cond);
8389 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008390
8391 pthread_mutex_lock(&adev->lock);
8392 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8393 if (out_ctxt != NULL) {
8394 list_remove(&out_ctxt->list);
8395 free(out_ctxt);
8396 } else {
8397 ALOGW("%s, output stream already closed", __func__);
8398 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008399 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008400 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008401 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008402}
8403
8404static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8405{
8406 struct audio_device *adev = (struct audio_device *)dev;
8407 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008408 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008409 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008410 int ret;
8411 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008412 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008413 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008414 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008415
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008416 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008417 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008418
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308419 if (!parms)
8420 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308421
Derek Chen6f293672019-04-01 01:40:24 -07008422 /* notify adev and input/output streams on the snd card status */
8423 adev_snd_mon_cb((void *)adev, parms);
8424
8425 list_for_each(node, &adev->active_outputs_list) {
8426 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8427 streams_output_ctxt_t,
8428 list);
8429 out_snd_mon_cb((void *)out_ctxt->output, parms);
8430 }
8431
8432 list_for_each(node, &adev->active_inputs_list) {
8433 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8434 streams_input_ctxt_t,
8435 list);
8436 in_snd_mon_cb((void *)in_ctxt->input, parms);
8437 }
8438
Zhou Songd6d71752019-05-21 18:08:51 +08008439 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308440 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8441 if (ret >= 0) {
8442 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008443 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308444 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008445 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308446 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008447 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008448 }
8449 }
8450
8451 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8452 if (ret>=0) {
8453 if (!strncmp(value, "false", 5) &&
8454 audio_extn_a2dp_source_is_suspended()) {
8455 struct audio_usecase *usecase;
8456 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008457 list_for_each(node, &adev->usecase_list) {
8458 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008459 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008460 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008461 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008462 reassign_device_list(&usecase->stream.in->device_list,
8463 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008464 select_devices(adev, usecase->id);
8465 }
Zhou Songd6d71752019-05-21 18:08:51 +08008466 }
8467 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308468 }
8469
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008470 status = voice_set_parameters(adev, parms);
8471 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008472 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008473
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008474 status = platform_set_parameters(adev->platform, parms);
8475 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008476 goto done;
8477
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008478 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8479 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008480 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008481 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8482 adev->bluetooth_nrec = true;
8483 else
8484 adev->bluetooth_nrec = false;
8485 }
8486
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008487 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8488 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008489 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8490 adev->screen_off = false;
8491 else
8492 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008493 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008494 }
8495
Eric Laurent4b084132018-10-19 17:33:43 -07008496 ret = str_parms_get_int(parms, "rotation", &val);
8497 if (ret >= 0) {
8498 bool reverse_speakers = false;
8499 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8500 switch (val) {
8501 // FIXME: note that the code below assumes that the speakers are in the correct placement
8502 // relative to the user when the device is rotated 90deg from its default rotation. This
8503 // assumption is device-specific, not platform-specific like this code.
8504 case 270:
8505 reverse_speakers = true;
8506 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8507 break;
8508 case 0:
8509 case 180:
8510 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8511 break;
8512 case 90:
8513 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8514 break;
8515 default:
8516 ALOGE("%s: unexpected rotation of %d", __func__, val);
8517 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008518 }
Eric Laurent4b084132018-10-19 17:33:43 -07008519 if (status == 0) {
8520 // check and set swap
8521 // - check if orientation changed and speaker active
8522 // - set rotation and cache the rotation value
8523 adev->camera_orientation =
8524 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8525 if (!audio_extn_is_maxx_audio_enabled())
8526 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8527 }
8528 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008529
Mingming Yin514a8bc2014-07-29 15:22:21 -07008530 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8531 if (ret >= 0) {
8532 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8533 adev->bt_wb_speech_enabled = true;
8534 else
8535 adev->bt_wb_speech_enabled = false;
8536 }
8537
Zhou Song12c29502019-03-16 10:37:18 +08008538 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8539 if (ret >= 0) {
8540 val = atoi(value);
8541 adev->swb_speech_mode = val;
8542 }
8543
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008544 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8545 if (ret >= 0) {
8546 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308547 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008548 if (audio_is_output_device(val) &&
8549 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008550 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008551 platform_get_controller_stream_from_params(parms, &controller, &stream);
8552 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8553 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008554 if (ret < 0) {
8555 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308556 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008557 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008558 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308559 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008560 /*
8561 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8562 * Per AudioPolicyManager, USB device is higher priority than WFD.
8563 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8564 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8565 * starting voice call on USB
8566 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008567 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308568 if (ret >= 0)
8569 audio_extn_usb_add_device(device, atoi(value));
8570
Zhou Song6f862822017-11-06 17:27:57 +08008571 if (!audio_extn_usb_is_tunnel_supported()) {
8572 ALOGV("detected USB connect .. disable proxy");
8573 adev->allow_afe_proxy_usage = false;
8574 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008575 }
8576 }
8577
8578 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8579 if (ret >= 0) {
8580 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308581 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008582 /*
8583 * The HDMI / Displayport disconnect handling has been moved to
8584 * audio extension to ensure that its parameters are not
8585 * invalidated prior to updating sysfs of the disconnect event
8586 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8587 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308588 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008589 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308590 if (ret >= 0)
8591 audio_extn_usb_remove_device(device, atoi(value));
8592
Zhou Song6f862822017-11-06 17:27:57 +08008593 if (!audio_extn_usb_is_tunnel_supported()) {
8594 ALOGV("detected USB disconnect .. enable proxy");
8595 adev->allow_afe_proxy_usage = true;
8596 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008597 }
8598 }
8599
Aalique Grahame22e49102018-12-18 14:23:57 -08008600 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008601 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008602
8603 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008604 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308605 struct audio_usecase *usecase;
8606 struct listnode *node;
8607 list_for_each(node, &adev->usecase_list) {
8608 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308609 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008610 is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308611 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008612 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308613 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008614 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308615 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308616 ALOGD("Switching to speaker and muting the stream before select_devices");
8617 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308618 //force device switch to re configure encoder
8619 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308620 ALOGD("Unmuting the stream after select_devices");
8621 usecase->stream.out->a2dp_compress_mute = false;
8622 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 +05308623 audio_extn_a2dp_set_handoff_mode(false);
8624 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308625 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308626 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8627 usecase->stream.out->a2dp_compress_mute) {
8628 pthread_mutex_unlock(&adev->lock);
8629 lock_output_stream(usecase->stream.out);
8630 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008631 reassign_device_list(&usecase->stream.out->device_list,
8632 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308633 check_a2dp_restore_l(adev, usecase->stream.out, true);
8634 pthread_mutex_unlock(&usecase->stream.out->lock);
8635 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308636 }
8637 }
8638 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008639
8640 //handle vr audio setparam
8641 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8642 value, sizeof(value));
8643 if (ret >= 0) {
8644 ALOGI("Setting vr mode to be %s", value);
8645 if (!strncmp(value, "true", 4)) {
8646 adev->vr_audio_mode_enabled = true;
8647 ALOGI("Setting vr mode to true");
8648 } else if (!strncmp(value, "false", 5)) {
8649 adev->vr_audio_mode_enabled = false;
8650 ALOGI("Setting vr mode to false");
8651 } else {
8652 ALOGI("wrong vr mode set");
8653 }
8654 }
8655
Eric Laurent4b084132018-10-19 17:33:43 -07008656 //FIXME: to be replaced by proper video capture properties API
8657 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8658 if (ret >= 0) {
8659 int camera_facing = CAMERA_FACING_BACK;
8660 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8661 camera_facing = CAMERA_FACING_FRONT;
8662 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8663 camera_facing = CAMERA_FACING_BACK;
8664 else {
8665 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8666 goto done;
8667 }
8668 adev->camera_orientation =
8669 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8670 struct audio_usecase *usecase;
8671 struct listnode *node;
8672 list_for_each(node, &adev->usecase_list) {
8673 usecase = node_to_item(node, struct audio_usecase, list);
8674 struct stream_in *in = usecase->stream.in;
8675 if (usecase->type == PCM_CAPTURE && in != NULL &&
8676 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8677 select_devices(adev, in->usecase);
8678 }
8679 }
8680 }
8681
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308682 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008683done:
8684 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008685 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308686error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008687 ALOGV("%s: exit with code(%d)", __func__, status);
8688 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008689}
8690
8691static char* adev_get_parameters(const struct audio_hw_device *dev,
8692 const char *keys)
8693{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308694 ALOGD("%s:%s", __func__, keys);
8695
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008696 struct audio_device *adev = (struct audio_device *)dev;
8697 struct str_parms *reply = str_parms_create();
8698 struct str_parms *query = str_parms_create_str(keys);
8699 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308700 char value[256] = {0};
8701 int ret = 0;
8702
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008703 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008704 if (reply) {
8705 str_parms_destroy(reply);
8706 }
8707 if (query) {
8708 str_parms_destroy(query);
8709 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008710 ALOGE("adev_get_parameters: failed to create query or reply");
8711 return NULL;
8712 }
8713
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008714 //handle vr audio getparam
8715
8716 ret = str_parms_get_str(query,
8717 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8718 value, sizeof(value));
8719
8720 if (ret >= 0) {
8721 bool vr_audio_enabled = false;
8722 pthread_mutex_lock(&adev->lock);
8723 vr_audio_enabled = adev->vr_audio_mode_enabled;
8724 pthread_mutex_unlock(&adev->lock);
8725
8726 ALOGI("getting vr mode to %d", vr_audio_enabled);
8727
8728 if (vr_audio_enabled) {
8729 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8730 "true");
8731 goto exit;
8732 } else {
8733 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8734 "false");
8735 goto exit;
8736 }
8737 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008738
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008739 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008740 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008741 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008742 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008743 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308744 pthread_mutex_unlock(&adev->lock);
8745
Naresh Tannirud7205b62014-06-20 02:54:48 +05308746exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008747 str = str_parms_to_str(reply);
8748 str_parms_destroy(query);
8749 str_parms_destroy(reply);
8750
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308751 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008752 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008753}
8754
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008755static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008756{
8757 return 0;
8758}
8759
8760static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8761{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008762 int ret;
8763 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008764
8765 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8766
Haynes Mathew George5191a852013-09-11 14:19:36 -07008767 pthread_mutex_lock(&adev->lock);
8768 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008769 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008770 pthread_mutex_unlock(&adev->lock);
8771 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008772}
8773
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008774static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8775 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008776{
8777 return -ENOSYS;
8778}
8779
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008780static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8781 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008782{
8783 return -ENOSYS;
8784}
8785
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008786static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8787 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008788{
8789 return -ENOSYS;
8790}
8791
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008792static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8793 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008794{
8795 return -ENOSYS;
8796}
8797
8798static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8799{
8800 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008801 struct listnode *node;
8802 struct audio_usecase *usecase = NULL;
8803 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008805 pthread_mutex_lock(&adev->lock);
8806 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008807 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008808 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008809 if (voice_is_in_call(adev) &&
8810 (mode == AUDIO_MODE_NORMAL ||
8811 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008812 list_for_each(node, &adev->usecase_list) {
8813 usecase = node_to_item(node, struct audio_usecase, list);
8814 if (usecase->type == VOICE_CALL)
8815 break;
8816 }
8817 if (usecase &&
8818 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8819 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8820 true);
8821 if (ret != 0) {
8822 /* default service interval was successfully updated,
8823 reopen USB backend with new service interval */
8824 check_usecases_codec_backend(adev,
8825 usecase,
8826 usecase->out_snd_device);
8827 }
8828 }
8829
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008830 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008831 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008832 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008833 // restore device for other active usecases after stop call
8834 list_for_each(node, &adev->usecase_list) {
8835 usecase = node_to_item(node, struct audio_usecase, list);
8836 select_devices(adev, usecase->id);
8837 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008838 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008839 }
8840 pthread_mutex_unlock(&adev->lock);
8841 return 0;
8842}
8843
8844static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8845{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008846 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008847 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008848
8849 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008850 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008851 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008852
Derek Chend2530072014-11-24 12:39:14 -08008853 if (adev->ext_hw_plugin)
8854 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008855
8856 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008857 pthread_mutex_unlock(&adev->lock);
8858
8859 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008860}
8861
8862static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8863{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008864 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008865 return 0;
8866}
8867
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008868static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008869 const struct audio_config *config)
8870{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008871 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008872
Aalique Grahame22e49102018-12-18 14:23:57 -08008873 /* Don't know if USB HIFI in this context so use true to be conservative */
8874 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8875 true /*is_usb_hifi */) != 0)
8876 return 0;
8877
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008878 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8879 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008880}
8881
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008882static bool adev_input_allow_hifi_record(struct audio_device *adev,
8883 audio_devices_t devices,
8884 audio_input_flags_t flags,
8885 audio_source_t source) {
8886 const bool allowed = true;
8887
8888 if (!audio_is_usb_in_device(devices))
8889 return !allowed;
8890
8891 switch (flags) {
8892 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008893 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008894 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8895 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008896 default:
8897 return !allowed;
8898 }
8899
8900 switch (source) {
8901 case AUDIO_SOURCE_DEFAULT:
8902 case AUDIO_SOURCE_MIC:
8903 case AUDIO_SOURCE_UNPROCESSED:
8904 break;
8905 default:
8906 return !allowed;
8907 }
8908
8909 switch (adev->mode) {
8910 case 0:
8911 break;
8912 default:
8913 return !allowed;
8914 }
8915
8916 return allowed;
8917}
8918
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008919static int adev_update_voice_comm_input_stream(struct stream_in *in,
8920 struct audio_config *config)
8921{
8922 bool valid_rate = (config->sample_rate == 8000 ||
8923 config->sample_rate == 16000 ||
8924 config->sample_rate == 32000 ||
8925 config->sample_rate == 48000);
8926 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8927
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008928 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008929 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008930 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8931 in->config = default_pcm_config_voip_copp;
8932 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8933 DEFAULT_VOIP_BUF_DURATION_MS,
8934 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008935 } else {
8936 ALOGW("%s No valid input in voip, use defaults"
8937 "sample rate %u, channel mask 0x%X",
8938 __func__, config->sample_rate, in->channel_mask);
8939 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008940 in->config.rate = config->sample_rate;
8941 in->sample_rate = config->sample_rate;
8942 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008943 //XXX needed for voice_extn_compress_voip_open_input_stream
8944 in->config.rate = config->sample_rate;
8945 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05308946 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008947 voice_extn_compress_voip_is_active(in->dev)) &&
8948 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8949 valid_rate && valid_ch) {
8950 voice_extn_compress_voip_open_input_stream(in);
8951 // update rate entries to match config from AF
8952 in->config.rate = config->sample_rate;
8953 in->sample_rate = config->sample_rate;
8954 } else {
8955 ALOGW("%s compress voip not active, use defaults", __func__);
8956 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008957 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008958 return 0;
8959}
8960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008961static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008962 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008963 audio_devices_t devices,
8964 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008965 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308966 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008967 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008968 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008969{
8970 struct audio_device *adev = (struct audio_device *)dev;
8971 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008972 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008973 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008974 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308975 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008976 bool is_usb_dev = audio_is_usb_in_device(devices);
8977 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8978 devices,
8979 flags,
8980 source);
Andy Hung94320602018-10-29 18:31:12 -07008981 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8982 " sample_rate %u, channel_mask %#x, format %#x",
8983 __func__, flags, is_usb_dev, may_use_hifi_record,
8984 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308985
kunleizdff872d2018-08-20 14:40:33 +08008986 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008987 is_usb_dev = false;
8988 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8989 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8990 __func__, devices);
8991 }
8992
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008993 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008994
8995 if (!(is_usb_dev && may_use_hifi_record)) {
8996 if (config->sample_rate == 0)
8997 config->sample_rate = 48000;
8998 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8999 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9000 if (config->format == AUDIO_FORMAT_DEFAULT)
9001 config->format = AUDIO_FORMAT_PCM_16_BIT;
9002
9003 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9004
Aalique Grahame22e49102018-12-18 14:23:57 -08009005 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9006 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009007 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309008 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009009
Rahul Sharma99770982019-03-06 17:05:26 +05309010 pthread_mutex_lock(&adev->lock);
9011 if (in_get_stream(adev, handle) != NULL) {
9012 ALOGW("%s, input stream already opened", __func__);
9013 ret = -EEXIST;
9014 }
9015 pthread_mutex_unlock(&adev->lock);
9016 if (ret)
9017 return ret;
9018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009019 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009020
9021 if (!in) {
9022 ALOGE("failed to allocate input stream");
9023 return -ENOMEM;
9024 }
9025
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309026 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309027 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9028 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009029 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009030 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009032 in->stream.common.get_sample_rate = in_get_sample_rate;
9033 in->stream.common.set_sample_rate = in_set_sample_rate;
9034 in->stream.common.get_buffer_size = in_get_buffer_size;
9035 in->stream.common.get_channels = in_get_channels;
9036 in->stream.common.get_format = in_get_format;
9037 in->stream.common.set_format = in_set_format;
9038 in->stream.common.standby = in_standby;
9039 in->stream.common.dump = in_dump;
9040 in->stream.common.set_parameters = in_set_parameters;
9041 in->stream.common.get_parameters = in_get_parameters;
9042 in->stream.common.add_audio_effect = in_add_audio_effect;
9043 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9044 in->stream.set_gain = in_set_gain;
9045 in->stream.read = in_read;
9046 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009047 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309048 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009049 in->stream.set_microphone_direction = in_set_microphone_direction;
9050 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009051 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009052
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009053 list_init(&in->device_list);
9054 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009055 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009056 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009057 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009058 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009059 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009060 in->bit_width = 16;
9061 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009062 in->direction = MIC_DIRECTION_UNSPECIFIED;
9063 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009064 list_init(&in->aec_list);
9065 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009066 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009067
Andy Hung94320602018-10-29 18:31:12 -07009068 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009069 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9070 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9071 /* Force channel config requested to mono if incall
9072 record is being requested for only uplink/downlink */
9073 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9074 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9075 ret = -EINVAL;
9076 goto err_open;
9077 }
9078 }
9079
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009080 if (is_usb_dev && may_use_hifi_record) {
9081 /* HiFi record selects an appropriate format, channel, rate combo
9082 depending on sink capabilities*/
9083 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9084 &config->format,
9085 &in->supported_formats[0],
9086 MAX_SUPPORTED_FORMATS,
9087 &config->channel_mask,
9088 &in->supported_channel_masks[0],
9089 MAX_SUPPORTED_CHANNEL_MASKS,
9090 &config->sample_rate,
9091 &in->supported_sample_rates[0],
9092 MAX_SUPPORTED_SAMPLE_RATES);
9093 if (ret != 0) {
9094 ret = -EINVAL;
9095 goto err_open;
9096 }
9097 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009098 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309099 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309100 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9101 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9102 in->config.format = PCM_FORMAT_S32_LE;
9103 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309104 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9105 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9106 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9107 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9108 bool ret_error = false;
9109 in->bit_width = 24;
9110 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9111 from HAL is 24_packed and 8_24
9112 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9113 24_packed return error indicating supported format is 24_packed
9114 *> In case of any other source requesting 24 bit or float return error
9115 indicating format supported is 16 bit only.
9116
9117 on error flinger will retry with supported format passed
9118 */
9119 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9120 (source != AUDIO_SOURCE_CAMCORDER)) {
9121 config->format = AUDIO_FORMAT_PCM_16_BIT;
9122 if (config->sample_rate > 48000)
9123 config->sample_rate = 48000;
9124 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009125 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9126 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309127 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9128 ret_error = true;
9129 }
9130
9131 if (ret_error) {
9132 ret = -EINVAL;
9133 goto err_open;
9134 }
9135 }
9136
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009137 in->channel_mask = config->channel_mask;
9138 in->format = config->format;
9139
9140 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309141
9142 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9143 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9144 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9145 else {
9146 ret = -EINVAL;
9147 goto err_open;
9148 }
9149 }
9150
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009151 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309152 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9153 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009154 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9155 is_low_latency = true;
9156#if LOW_LATENCY_CAPTURE_USE_CASE
9157 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9158#endif
9159 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009160 if (!in->realtime) {
9161 in->config = pcm_config_audio_capture;
9162 frame_size = audio_stream_in_frame_size(&in->stream);
9163 buffer_size = get_input_buffer_size(config->sample_rate,
9164 config->format,
9165 channel_count,
9166 is_low_latency);
9167 in->config.period_size = buffer_size / frame_size;
9168 in->config.rate = config->sample_rate;
9169 in->af_period_multiplier = 1;
9170 } else {
9171 // period size is left untouched for rt mode playback
9172 in->config = pcm_config_audio_capture_rt;
9173 in->af_period_multiplier = af_period_multiplier;
9174 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009175 }
9176
9177 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9178 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9179 in->realtime = 0;
9180 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9181 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009182 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009183 in->stream.start = in_start;
9184 in->stream.stop = in_stop;
9185 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9186 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009187 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
9188 } else if (in->realtime) {
9189 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07009190 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009191 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009192 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009193 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9194 in->config = pcm_config_audio_capture;
9195 frame_size = audio_stream_in_frame_size(&in->stream);
9196 buffer_size = get_input_buffer_size(config->sample_rate,
9197 config->format,
9198 channel_count,
9199 false /*is_low_latency*/);
9200 in->config.period_size = buffer_size / frame_size;
9201 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009202 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009203 switch (config->format) {
9204 case AUDIO_FORMAT_PCM_32_BIT:
9205 in->bit_width = 32;
9206 break;
9207 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9208 case AUDIO_FORMAT_PCM_8_24_BIT:
9209 in->bit_width = 24;
9210 break;
9211 default:
9212 in->bit_width = 16;
9213 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009214 } else if (is_single_device_type_equal(&in->device_list,
9215 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9216 is_single_device_type_equal(&in->device_list,
9217 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009218 if (config->sample_rate == 0)
9219 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9220 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9221 config->sample_rate != 8000) {
9222 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9223 ret = -EINVAL;
9224 goto err_open;
9225 }
9226 if (config->format == AUDIO_FORMAT_DEFAULT)
9227 config->format = AUDIO_FORMAT_PCM_16_BIT;
9228 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9229 config->format = AUDIO_FORMAT_PCM_16_BIT;
9230 ret = -EINVAL;
9231 goto err_open;
9232 }
9233
9234 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
9235 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009236 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009237 in->af_period_multiplier = 1;
9238 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9239 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9240 (config->sample_rate == 8000 ||
9241 config->sample_rate == 16000 ||
9242 config->sample_rate == 32000 ||
9243 config->sample_rate == 48000) &&
9244 channel_count == 1) {
9245 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9246 in->config = pcm_config_audio_capture;
9247 frame_size = audio_stream_in_frame_size(&in->stream);
9248 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9249 config->sample_rate,
9250 config->format,
9251 channel_count, false /*is_low_latency*/);
9252 in->config.period_size = buffer_size / frame_size;
9253 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9254 in->config.rate = config->sample_rate;
9255 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009256 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309257 int ret_val;
9258 pthread_mutex_lock(&adev->lock);
9259 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9260 in, config, &channel_mask_updated);
9261 pthread_mutex_unlock(&adev->lock);
9262
9263 if (!ret_val) {
9264 if (channel_mask_updated == true) {
9265 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9266 __func__, config->channel_mask);
9267 ret = -EINVAL;
9268 goto err_open;
9269 }
9270 ALOGD("%s: created multi-channel session succesfully",__func__);
9271 } else if (audio_extn_compr_cap_enabled() &&
9272 audio_extn_compr_cap_format_supported(config->format) &&
9273 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9274 audio_extn_compr_cap_init(in);
9275 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309276 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309277 if (ret)
9278 goto err_open;
9279 } else {
9280 in->config = pcm_config_audio_capture;
9281 in->config.rate = config->sample_rate;
9282 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309283 in->format = config->format;
9284 frame_size = audio_stream_in_frame_size(&in->stream);
9285 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009286 config->format,
9287 channel_count,
9288 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009289 /* prevent division-by-zero */
9290 if (frame_size == 0) {
9291 ALOGE("%s: Error frame_size==0", __func__);
9292 ret = -EINVAL;
9293 goto err_open;
9294 }
9295
Revathi Uddarajud2634032017-12-07 14:42:34 +05309296 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009297 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009298
Revathi Uddarajud2634032017-12-07 14:42:34 +05309299 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9300 /* optionally use VOIP usecase depending on config(s) */
9301 ret = adev_update_voice_comm_input_stream(in, config);
9302 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009303
Revathi Uddarajud2634032017-12-07 14:42:34 +05309304 if (ret) {
9305 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9306 goto err_open;
9307 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009308 }
Samyak Jainc37062f2019-04-25 18:41:06 +05309309 if (audio_extn_is_concurrent_capture_enabled()) {
9310 /* Acquire lock to avoid two concurrent use cases initialized to
9311 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009312
Samyak Jainc37062f2019-04-25 18:41:06 +05309313 if (in->usecase == USECASE_AUDIO_RECORD) {
9314 pthread_mutex_lock(&adev->lock);
9315 if (!(adev->pcm_record_uc_state)) {
9316 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9317 adev->pcm_record_uc_state = 1;
9318 pthread_mutex_unlock(&adev->lock);
9319 } else {
9320 pthread_mutex_unlock(&adev->lock);
9321 /* Assign compress record use case for second record */
9322 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9323 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9324 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9325 if (audio_extn_cin_applicable_stream(in)) {
9326 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309327 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309328 if (ret)
9329 goto err_open;
9330 }
9331 }
9332 }
kunleiz28c73e72019-03-27 17:24:04 +08009333 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009334 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309335 if (audio_extn_ssr_get_stream() != in)
9336 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009337
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009338 in->sample_rate = in->config.rate;
9339
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309340 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9341 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009342 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009343 in->sample_rate, in->bit_width,
9344 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309345 register_format(in->format, in->supported_formats);
9346 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9347 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309348
Aalique Grahame22e49102018-12-18 14:23:57 -08009349 in->error_log = error_log_create(
9350 ERROR_LOG_ENTRIES,
9351 1000000000 /* aggregate consecutive identical errors within one second */);
9352
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009353 /* This stream could be for sound trigger lab,
9354 get sound trigger pcm if present */
9355 audio_extn_sound_trigger_check_and_get_session(in);
9356
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309357 lock_input_stream(in);
9358 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9359 pthread_mutex_lock(&adev->lock);
9360 in->card_status = adev->card_status;
9361 pthread_mutex_unlock(&adev->lock);
9362 pthread_mutex_unlock(&in->lock);
9363
Aalique Grahame22e49102018-12-18 14:23:57 -08009364 stream_app_type_cfg_init(&in->app_type_cfg);
9365
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009366 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009367
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009368 ret = io_streams_map_insert(adev, &in->stream.common,
9369 handle, AUDIO_PATCH_HANDLE_NONE);
9370 if (ret != 0)
9371 goto err_open;
9372
Derek Chenf939fb72018-11-13 13:34:41 -08009373 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9374 calloc(1, sizeof(streams_input_ctxt_t));
9375 if (in_ctxt == NULL) {
9376 ALOGE("%s fail to allocate input ctxt", __func__);
9377 ret = -ENOMEM;
9378 goto err_open;
9379 }
9380 in_ctxt->input = in;
9381
9382 pthread_mutex_lock(&adev->lock);
9383 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9384 pthread_mutex_unlock(&adev->lock);
9385
Eric Laurent994a6932013-07-17 11:51:42 -07009386 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009387 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009388
9389err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309390 if (in->usecase == USECASE_AUDIO_RECORD) {
9391 pthread_mutex_lock(&adev->lock);
9392 adev->pcm_record_uc_state = 0;
9393 pthread_mutex_unlock(&adev->lock);
9394 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009395 free(in);
9396 *stream_in = NULL;
9397 return ret;
9398}
9399
9400static void adev_close_input_stream(struct audio_hw_device *dev,
9401 struct audio_stream_in *stream)
9402{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009403 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009404 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009405 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309406
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309407 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009408
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009409 if (in == NULL) {
9410 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9411 return;
9412 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009413 io_streams_map_remove(adev, in->capture_handle);
9414
kunleiz70e57612018-12-28 17:50:23 +08009415 /* must deregister from sndmonitor first to prevent races
9416 * between the callback and close_stream
9417 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309418 audio_extn_snd_mon_unregister_listener(stream);
9419
kunleiz70e57612018-12-28 17:50:23 +08009420 /* Disable echo reference if there are no active input, hfp call
9421 * and sound trigger while closing input stream
9422 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009423 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009424 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009425 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9426 struct listnode out_devices;
9427 list_init(&out_devices);
9428 platform_set_echo_reference(adev, false, &out_devices);
9429 } else
kunleiz70e57612018-12-28 17:50:23 +08009430 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309431
Weiyin Jiang2995f662019-04-17 14:25:12 +08009432 error_log_destroy(in->error_log);
9433 in->error_log = NULL;
9434
Pallavid7c7a272018-01-16 11:22:55 +05309435
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009436 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309437 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009438 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309439 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009440 if (ret != 0)
9441 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9442 __func__, ret);
9443 } else
9444 in_standby(&stream->common);
9445
Revathi Uddarajud2634032017-12-07 14:42:34 +05309446 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309447 if (in->usecase == USECASE_AUDIO_RECORD) {
9448 adev->pcm_record_uc_state = 0;
9449 }
9450
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009451 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009452 audio_extn_ssr_deinit();
9453 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009454
Garmond Leunge2433c32017-09-28 21:51:22 -07009455 if (audio_extn_ffv_get_stream() == in) {
9456 audio_extn_ffv_stream_deinit();
9457 }
9458
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309459 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009460 audio_extn_compr_cap_format_supported(in->config.format))
9461 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309462
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309463 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05309464 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009465
Mingming Yinfd7607b2016-01-22 12:48:44 -08009466 if (in->is_st_session) {
9467 ALOGV("%s: sound trigger pcm stop lab", __func__);
9468 audio_extn_sound_trigger_stop_lab(in);
9469 }
Derek Chenf939fb72018-11-13 13:34:41 -08009470 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9471 if (in_ctxt != NULL) {
9472 list_remove(&in_ctxt->list);
9473 free(in_ctxt);
9474 } else {
9475 ALOGW("%s, input stream already closed", __func__);
9476 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009477 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309478 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009479 return;
9480}
9481
Aalique Grahame22e49102018-12-18 14:23:57 -08009482/* verifies input and output devices and their capabilities.
9483 *
9484 * This verification is required when enabling extended bit-depth or
9485 * sampling rates, as not all qcom products support it.
9486 *
9487 * Suitable for calling only on initialization such as adev_open().
9488 * It fills the audio_device use_case_table[] array.
9489 *
9490 * Has a side-effect that it needs to configure audio routing / devices
9491 * in order to power up the devices and read the device parameters.
9492 * It does not acquire any hw device lock. Should restore the devices
9493 * back to "normal state" upon completion.
9494 */
9495static int adev_verify_devices(struct audio_device *adev)
9496{
9497 /* enumeration is a bit difficult because one really wants to pull
9498 * the use_case, device id, etc from the hidden pcm_device_table[].
9499 * In this case there are the following use cases and device ids.
9500 *
9501 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9502 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9503 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9504 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9505 * [USECASE_AUDIO_RECORD] = {0, 0},
9506 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9507 * [USECASE_VOICE_CALL] = {2, 2},
9508 *
9509 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9510 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9511 */
9512
9513 /* should be the usecases enabled in adev_open_input_stream() */
9514 static const int test_in_usecases[] = {
9515 USECASE_AUDIO_RECORD,
9516 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9517 };
9518 /* should be the usecases enabled in adev_open_output_stream()*/
9519 static const int test_out_usecases[] = {
9520 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9521 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9522 };
9523 static const usecase_type_t usecase_type_by_dir[] = {
9524 PCM_PLAYBACK,
9525 PCM_CAPTURE,
9526 };
9527 static const unsigned flags_by_dir[] = {
9528 PCM_OUT,
9529 PCM_IN,
9530 };
9531
9532 size_t i;
9533 unsigned dir;
9534 const unsigned card_id = adev->snd_card;
9535
9536 for (dir = 0; dir < 2; ++dir) {
9537 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9538 const unsigned flags_dir = flags_by_dir[dir];
9539 const size_t testsize =
9540 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9541 const int *testcases =
9542 dir ? test_in_usecases : test_out_usecases;
9543 const audio_devices_t audio_device =
9544 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9545
9546 for (i = 0; i < testsize; ++i) {
9547 const audio_usecase_t audio_usecase = testcases[i];
9548 int device_id;
9549 struct pcm_params **pparams;
9550 struct stream_out out;
9551 struct stream_in in;
9552 struct audio_usecase uc_info;
9553 int retval;
9554
9555 pparams = &adev->use_case_table[audio_usecase];
9556 pcm_params_free(*pparams); /* can accept null input */
9557 *pparams = NULL;
9558
9559 /* find the device ID for the use case (signed, for error) */
9560 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9561 if (device_id < 0)
9562 continue;
9563
9564 /* prepare structures for device probing */
9565 memset(&uc_info, 0, sizeof(uc_info));
9566 uc_info.id = audio_usecase;
9567 uc_info.type = usecase_type;
9568 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009569 memset(&in, 0, sizeof(in));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009570 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009571 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9572 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009573 }
9574 memset(&out, 0, sizeof(out));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009575 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009576 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009577 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009578 uc_info.in_snd_device = SND_DEVICE_NONE;
9579 uc_info.out_snd_device = SND_DEVICE_NONE;
9580 list_add_tail(&adev->usecase_list, &uc_info.list);
9581
9582 /* select device - similar to start_(in/out)put_stream() */
9583 retval = select_devices(adev, audio_usecase);
9584 if (retval >= 0) {
9585 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9586#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009587 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009588 if (*pparams) {
9589 ALOGV("%s: (%s) card %d device %d", __func__,
9590 dir ? "input" : "output", card_id, device_id);
9591 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9592 } else {
9593 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9594 }
9595#endif
9596 }
9597
9598 /* deselect device - similar to stop_(in/out)put_stream() */
9599 /* 1. Get and set stream specific mixer controls */
9600 retval = disable_audio_route(adev, &uc_info);
9601 /* 2. Disable the rx device */
9602 retval = disable_snd_device(adev,
9603 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9604 list_remove(&uc_info.list);
9605 }
9606 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009607 return 0;
9608}
9609
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009610int update_patch(unsigned int num_sources,
9611 const struct audio_port_config *sources,
9612 unsigned int num_sinks,
9613 const struct audio_port_config *sinks,
9614 audio_patch_handle_t handle,
9615 struct audio_patch_info *p_info,
9616 patch_type_t patch_type, bool new_patch)
9617{
9618 ALOGD("%s: enter", __func__);
9619
9620 if (p_info == NULL) {
9621 ALOGE("%s: Invalid patch pointer", __func__);
9622 return -EINVAL;
9623 }
9624
9625 if (new_patch) {
9626 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9627 if (p_info->patch == NULL) {
9628 ALOGE("%s: Could not allocate patch", __func__);
9629 return -ENOMEM;
9630 }
9631 }
9632
9633 p_info->patch->id = handle;
9634 p_info->patch->num_sources = num_sources;
9635 p_info->patch->num_sinks = num_sinks;
9636
9637 for (int i = 0; i < num_sources; i++)
9638 p_info->patch->sources[i] = sources[i];
9639 for (int i = 0; i < num_sinks; i++)
9640 p_info->patch->sinks[i] = sinks[i];
9641
9642 p_info->patch_type = patch_type;
9643 return 0;
9644}
9645
9646audio_patch_handle_t generate_patch_handle()
9647{
9648 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9649 if (++patch_handle < 0)
9650 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9651 return patch_handle;
9652}
9653
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309654int adev_create_audio_patch(struct audio_hw_device *dev,
9655 unsigned int num_sources,
9656 const struct audio_port_config *sources,
9657 unsigned int num_sinks,
9658 const struct audio_port_config *sinks,
9659 audio_patch_handle_t *handle)
9660{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009661 int ret = 0;
9662 struct audio_device *adev = (struct audio_device *)dev;
9663 struct audio_patch_info *p_info = NULL;
9664 patch_type_t patch_type = PATCH_NONE;
9665 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9666 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9667 struct audio_stream_info *s_info = NULL;
9668 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009669 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009670 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9671 bool new_patch = false;
9672 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309673
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009674 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9675 num_sources, num_sinks, *handle);
9676
9677 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9678 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9679 ALOGE("%s: Invalid patch arguments", __func__);
9680 ret = -EINVAL;
9681 goto done;
9682 }
9683
9684 if (num_sources > 1) {
9685 ALOGE("%s: Multiple sources are not supported", __func__);
9686 ret = -EINVAL;
9687 goto done;
9688 }
9689
9690 if (sources == NULL || sinks == NULL) {
9691 ALOGE("%s: Invalid sources or sinks port config", __func__);
9692 ret = -EINVAL;
9693 goto done;
9694 }
9695
9696 ALOGV("%s: source role %d, source type %d", __func__,
9697 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009698 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009699
9700 // Populate source/sink information and fetch stream info
9701 switch (sources[0].type) {
9702 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9703 device_type = sources[0].ext.device.type;
9704 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009705 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009706 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9707 patch_type = PATCH_CAPTURE;
9708 io_handle = sinks[0].ext.mix.handle;
9709 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009710 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009711 __func__, device_type, io_handle);
9712 } else {
9713 // Device to device patch is not implemented.
9714 // This space will need changes if audio HAL
9715 // handles device to device patches in the future.
9716 patch_type = PATCH_DEVICE_LOOPBACK;
9717 }
9718 break;
9719 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9720 io_handle = sources[0].ext.mix.handle;
9721 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009722 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009723 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009724 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009725 }
9726 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009727 ALOGD("%s: Playback patch from mix handle %d to device %x",
9728 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009729 break;
9730 case AUDIO_PORT_TYPE_SESSION:
9731 case AUDIO_PORT_TYPE_NONE:
9732 break;
9733 }
9734
9735 pthread_mutex_lock(&adev->lock);
9736 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9737 pthread_mutex_unlock(&adev->lock);
9738 if (s_info == NULL) {
9739 ALOGE("%s: Failed to obtain stream info", __func__);
9740 ret = -EINVAL;
9741 goto done;
9742 }
9743 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9744
9745 pthread_mutex_lock(&s_info->lock);
9746 // Generate patch info and update patch
9747 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
9748 if (s_info->patch_handle != AUDIO_PATCH_HANDLE_NONE) {
9749 // Use patch handle cached in s_info to update patch
9750 *handle = s_info->patch_handle;
9751 p_info = fetch_patch_info(adev, *handle);
9752 if (p_info == NULL) {
9753 ALOGE("%s: Unable to fetch patch for stream patch handle %d",
9754 __func__, *handle);
9755 pthread_mutex_unlock(&s_info->lock);
9756 ret = -EINVAL;
9757 goto done;
9758 }
9759 } else {
9760 *handle = generate_patch_handle();
9761 p_info = (struct audio_patch_info *) calloc(1, sizeof(struct audio_patch_info));
9762 if (p_info == NULL) {
9763 ALOGE("%s: Failed to allocate memory", __func__);
9764 pthread_mutex_unlock(&s_info->lock);
9765 ret = -ENOMEM;
9766 goto done;
9767 }
9768 new_patch = true;
9769 pthread_mutex_init(&p_info->lock, (const pthread_mutexattr_t *) NULL);
9770 s_info->patch_handle = *handle;
9771 }
9772 } else {
9773 p_info = fetch_patch_info(adev, *handle);
9774 if (p_info == NULL) {
9775 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9776 __func__, *handle);
9777 pthread_mutex_unlock(&s_info->lock);
9778 ret = -EINVAL;
9779 goto done;
9780 }
9781 s_info->patch_handle = *handle;
9782 }
9783 pthread_mutex_lock(&p_info->lock);
9784 update_patch(num_sources, sources, num_sinks, sinks,
9785 *handle, p_info, patch_type, new_patch);
9786 stream = s_info->stream;
9787
9788 // Update routing for stream
9789 if (stream != NULL) {
9790 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009791 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009792 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009793 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009794 }
9795
9796 if (ret < 0) {
9797 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9798 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9799 pthread_mutex_unlock(&p_info->lock);
9800 pthread_mutex_unlock(&s_info->lock);
9801 goto done;
9802 }
9803
9804 // Add new patch to patch map
9805 if (!ret && new_patch) {
9806 pthread_mutex_lock(&adev->lock);
9807 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
9808 pthread_mutex_unlock(&adev->lock);
9809 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
9810 }
9811
9812 pthread_mutex_unlock(&p_info->lock);
9813 pthread_mutex_unlock(&s_info->lock);
9814done:
9815 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009816 num_sources,
9817 sources,
9818 num_sinks,
9819 sinks,
9820 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009821 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009822 num_sources,
9823 sources,
9824 num_sinks,
9825 sinks,
9826 handle);
9827 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309828}
9829
9830int adev_release_audio_patch(struct audio_hw_device *dev,
9831 audio_patch_handle_t handle)
9832{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009833 struct audio_device *adev = (struct audio_device *) dev;
9834 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009835 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Derek Chenf939fb72018-11-13 13:34:41 -08009836
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009837 if (handle == AUDIO_PATCH_HANDLE_NONE) {
9838 ALOGE("%s: Invalid patch handle %d", __func__, handle);
9839 ret = -EINVAL;
9840 goto done;
9841 }
9842
9843 ALOGD("%s: Remove patch with handle %d", __func__, handle);
9844 struct audio_patch_info *p_info = fetch_patch_info(adev, handle);
9845 if (p_info == NULL) {
9846 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
9847 ret = -EINVAL;
9848 goto done;
9849 }
9850 pthread_mutex_lock(&p_info->lock);
9851 struct audio_patch *patch = p_info->patch;
9852 if (patch == NULL) {
9853 ALOGE("%s: Patch not found for handle %d", __func__, handle);
9854 ret = -EINVAL;
9855 pthread_mutex_unlock(&p_info->lock);
9856 goto done;
9857 }
9858 pthread_mutex_unlock(&p_info->lock);
9859 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9860 switch (patch->sources[0].type) {
9861 case AUDIO_PORT_TYPE_MIX:
9862 io_handle = patch->sources[0].ext.mix.handle;
9863 break;
9864 case AUDIO_PORT_TYPE_DEVICE:
9865 io_handle = patch->sinks[0].ext.mix.handle;
9866 break;
9867 case AUDIO_PORT_TYPE_SESSION:
9868 case AUDIO_PORT_TYPE_NONE:
9869 break;
9870 }
9871
9872 // Remove patch and reset patch handle in stream info
9873 pthread_mutex_lock(&adev->lock);
9874 struct audio_stream_info *s_info =
9875 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9876 pthread_mutex_unlock(&adev->lock);
9877 if (s_info == NULL) {
9878 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
9879 goto done;
9880 }
9881 pthread_mutex_lock(&s_info->lock);
9882 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9883 struct audio_stream *stream = s_info->stream;
9884
9885 pthread_mutex_lock(&p_info->lock);
9886 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009887 struct listnode devices;
9888 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009889 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009890 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009891 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009892 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009893 }
9894
9895 if (ret < 0)
9896 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9897
9898 pthread_mutex_unlock(&p_info->lock);
9899 pthread_mutex_unlock(&s_info->lock);
9900
9901 // Remove patch entry from map
9902 patch_map_remove(adev, handle);
9903done:
9904 audio_extn_hw_loopback_release_audio_patch(dev, handle);
9905 audio_extn_auto_hal_release_audio_patch(dev, handle);
9906
9907 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -08009908 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309909}
9910
9911int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9912{
Derek Chenf13dd492018-11-13 14:53:51 -08009913 int ret = 0;
9914
9915 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9916 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9917 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309918}
9919
9920int adev_set_audio_port_config(struct audio_hw_device *dev,
9921 const struct audio_port_config *config)
9922{
Derek Chenf13dd492018-11-13 14:53:51 -08009923 int ret = 0;
9924
9925 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9926 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9927 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309928}
9929
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009930static int adev_dump(const audio_hw_device_t *device __unused,
9931 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009932{
9933 return 0;
9934}
9935
9936static int adev_close(hw_device_t *device)
9937{
Aalique Grahame22e49102018-12-18 14:23:57 -08009938 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309939 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009940
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309941 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009942 return 0;
9943
9944 pthread_mutex_lock(&adev_init_lock);
9945
9946 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309947 if (audio_extn_spkr_prot_is_enabled())
9948 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +05309949 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309950 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009951 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009952 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009953 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009954 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309955 audio_extn_utils_release_streams_cfg_lists(
9956 &adev->streams_output_cfg_list,
9957 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309958 if (audio_extn_qap_is_enabled())
9959 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309960 if (audio_extn_qaf_is_enabled())
9961 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009962 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009963 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009964 free(adev->snd_dev_ref_cnt);
9965 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009966 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9967 pcm_params_free(adev->use_case_table[i]);
9968 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009969 if (adev->adm_deinit)
9970 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309971 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009972 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309973 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309974 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009975 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309976 if (adev->device_cfg_params) {
9977 free(adev->device_cfg_params);
9978 adev->device_cfg_params = NULL;
9979 }
Derek Chend2530072014-11-24 12:39:14 -08009980 if(adev->ext_hw_plugin)
9981 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08009982 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009983 free_map(adev->patch_map);
9984 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -07009985 free(device);
9986 adev = NULL;
9987 }
9988 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05309989 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009990 return 0;
9991}
9992
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009993/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
9994 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
9995 * just that it _might_ work.
9996 */
9997static int period_size_is_plausible_for_low_latency(int period_size)
9998{
9999 switch (period_size) {
10000 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010001 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010002 case 240:
10003 case 320:
10004 case 480:
10005 return 1;
10006 default:
10007 return 0;
10008 }
10009}
10010
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010011static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10012{
10013 bool is_snd_card_status = false;
10014 bool is_ext_device_status = false;
10015 char value[32];
10016 int card = -1;
10017 card_status_t status;
10018
10019 if (cookie != adev || !parms)
10020 return;
10021
10022 if (!parse_snd_card_status(parms, &card, &status)) {
10023 is_snd_card_status = true;
10024 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10025 is_ext_device_status = true;
10026 } else {
10027 // not a valid event
10028 return;
10029 }
10030
10031 pthread_mutex_lock(&adev->lock);
10032 if (card == adev->snd_card || is_ext_device_status) {
10033 if (is_snd_card_status && adev->card_status != status) {
10034 adev->card_status = status;
10035 platform_snd_card_update(adev->platform, status);
10036 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010037 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010038 if (status == CARD_STATUS_OFFLINE)
10039 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010040 } else if (is_ext_device_status) {
10041 platform_set_parameters(adev->platform, parms);
10042 }
10043 }
10044 pthread_mutex_unlock(&adev->lock);
10045 return;
10046}
10047
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010048/* out and adev lock held */
10049static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10050{
10051 struct audio_usecase *uc_info;
10052 float left_p;
10053 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010054 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010055
10056 uc_info = get_usecase_from_list(adev, out->usecase);
10057 if (uc_info == NULL) {
10058 ALOGE("%s: Could not find the usecase (%d) in the list",
10059 __func__, out->usecase);
10060 return -EINVAL;
10061 }
10062
10063 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10064 out->usecase, use_case_table[out->usecase]);
10065
10066 if (restore) {
10067 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010068 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010069 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010070 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10071 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010072 pthread_mutex_lock(&out->compr_mute_lock);
10073 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010074 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010075 out->a2dp_compress_mute = false;
10076 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10077 }
10078 pthread_mutex_unlock(&out->compr_mute_lock);
10079 }
10080 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010081 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10082 // mute compress stream if suspended
10083 pthread_mutex_lock(&out->compr_mute_lock);
10084 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010085 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010086 assign_devices(&devices, &out->device_list);
10087 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010088 left_p = out->volume_l;
10089 right_p = out->volume_r;
10090 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10091 compress_pause(out->compr);
10092 out_set_compr_volume(&out->stream, (float)0, (float)0);
10093 out->a2dp_compress_mute = true;
10094 select_devices(adev, out->usecase);
10095 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10096 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010097 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010098 out->volume_l = left_p;
10099 out->volume_r = right_p;
10100 }
Zhou Songc576a452019-09-09 14:17:40 +080010101 pthread_mutex_unlock(&out->compr_mute_lock);
10102 } else {
10103 // tear down a2dp path for non offloaded streams
10104 if (audio_extn_a2dp_source_is_suspended())
10105 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010106 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010107 }
10108 ALOGV("%s: exit", __func__);
10109 return 0;
10110}
10111
10112int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10113{
10114 int ret = 0;
10115
10116 lock_output_stream(out);
10117 pthread_mutex_lock(&adev->lock);
10118
10119 ret = check_a2dp_restore_l(adev, out, restore);
10120
10121 pthread_mutex_unlock(&adev->lock);
10122 pthread_mutex_unlock(&out->lock);
10123 return ret;
10124}
10125
Haynes Mathew George01156f92018-04-13 15:29:54 -070010126void adev_on_battery_status_changed(bool charging)
10127{
10128 pthread_mutex_lock(&adev->lock);
10129 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10130 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010131 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010132 pthread_mutex_unlock(&adev->lock);
10133}
10134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010135static int adev_open(const hw_module_t *module, const char *name,
10136 hw_device_t **device)
10137{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010138 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010139 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010140 char mixer_ctl_name[128] = {0};
10141 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010142
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010143 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010144 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10145
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010146 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010147 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010148 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010149 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010150 ALOGD("%s: returning existing instance of adev", __func__);
10151 ALOGD("%s: exit", __func__);
10152 pthread_mutex_unlock(&adev_init_lock);
10153 return 0;
10154 }
10155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010156 adev = calloc(1, sizeof(struct audio_device));
10157
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010158 if (!adev) {
10159 pthread_mutex_unlock(&adev_init_lock);
10160 return -ENOMEM;
10161 }
10162
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010163 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10164
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010165 // register audio ext hidl at the earliest
10166 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010167#ifdef DYNAMIC_LOG_ENABLED
10168 register_for_dynamic_logging("hal");
10169#endif
10170
Derek Chenf939fb72018-11-13 13:34:41 -080010171 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010172 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010173 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10174 maj_version = atoi(value);
10175
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010176 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010177 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010178 adev->device.common.module = (struct hw_module_t *)module;
10179 adev->device.common.close = adev_close;
10180
10181 adev->device.init_check = adev_init_check;
10182 adev->device.set_voice_volume = adev_set_voice_volume;
10183 adev->device.set_master_volume = adev_set_master_volume;
10184 adev->device.get_master_volume = adev_get_master_volume;
10185 adev->device.set_master_mute = adev_set_master_mute;
10186 adev->device.get_master_mute = adev_get_master_mute;
10187 adev->device.set_mode = adev_set_mode;
10188 adev->device.set_mic_mute = adev_set_mic_mute;
10189 adev->device.get_mic_mute = adev_get_mic_mute;
10190 adev->device.set_parameters = adev_set_parameters;
10191 adev->device.get_parameters = adev_get_parameters;
10192 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10193 adev->device.open_output_stream = adev_open_output_stream;
10194 adev->device.close_output_stream = adev_close_output_stream;
10195 adev->device.open_input_stream = adev_open_input_stream;
10196 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010197 adev->device.create_audio_patch = adev_create_audio_patch;
10198 adev->device.release_audio_patch = adev_release_audio_patch;
10199 adev->device.get_audio_port = adev_get_audio_port;
10200 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010201 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010202 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010203
10204 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010205 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010206 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010207 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010208 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010209 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010210 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010211 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010212 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010213 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010214 /* Init audio and voice feature */
10215 audio_extn_feature_init();
10216 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010217 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010218 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010219 list_init(&adev->active_inputs_list);
10220 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010221 list_init(&adev->audio_patch_record_list);
10222 adev->audio_patch_index = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010223 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10224 audio_extn_utils_hash_eq);
10225 if (!adev->io_streams_map) {
10226 ALOGE("%s: Could not create io streams map", __func__);
10227 ret = -ENOMEM;
10228 goto adev_open_err;
10229 }
10230 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10231 audio_extn_utils_hash_eq);
10232 if (!adev->patch_map) {
10233 ALOGE("%s: Could not create audio patch map", __func__);
10234 ret = -ENOMEM;
10235 goto adev_open_err;
10236 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010237 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010238 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010239 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010240 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010241 adev->perf_lock_opts[0] = 0x101;
10242 adev->perf_lock_opts[1] = 0x20E;
10243 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010244 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010245 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010246 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010247 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010249 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010250 adev->platform = platform_init(adev);
10251 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010252 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010253 ret = -EINVAL;
10254 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010255 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010256
Aalique Grahame22e49102018-12-18 14:23:57 -080010257 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010258 if (audio_extn_qap_is_enabled()) {
10259 ret = audio_extn_qap_init(adev);
10260 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010261 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010262 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010263 }
10264 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10265 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10266 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010267
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010268 if (audio_extn_qaf_is_enabled()) {
10269 ret = audio_extn_qaf_init(adev);
10270 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010271 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010272 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010273 }
10274
10275 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10276 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10277 }
10278
Derek Chenae7b0342019-02-08 15:17:04 -080010279 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010280 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10281
Eric Laurentc4aef752013-09-12 17:45:53 -070010282 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10283 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10284 if (adev->visualizer_lib == NULL) {
10285 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10286 } else {
10287 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10288 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010289 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010290 "visualizer_hal_start_output");
10291 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010292 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010293 "visualizer_hal_stop_output");
10294 }
10295 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010296 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010297 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010298 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010299 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010300 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010301 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010302
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010303 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10304 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10305 if (adev->offload_effects_lib == NULL) {
10306 ALOGE("%s: DLOPEN failed for %s", __func__,
10307 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10308 } else {
10309 ALOGV("%s: DLOPEN successful for %s", __func__,
10310 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10311 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010312 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010313 "offload_effects_bundle_hal_start_output");
10314 adev->offload_effects_stop_output =
10315 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10316 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010317 adev->offload_effects_set_hpx_state =
10318 (int (*)(bool))dlsym(adev->offload_effects_lib,
10319 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010320 adev->offload_effects_get_parameters =
10321 (void (*)(struct str_parms *, struct str_parms *))
10322 dlsym(adev->offload_effects_lib,
10323 "offload_effects_bundle_get_parameters");
10324 adev->offload_effects_set_parameters =
10325 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10326 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010327 }
10328 }
10329
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010330 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10331 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10332 if (adev->adm_lib == NULL) {
10333 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10334 } else {
10335 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10336 adev->adm_init = (adm_init_t)
10337 dlsym(adev->adm_lib, "adm_init");
10338 adev->adm_deinit = (adm_deinit_t)
10339 dlsym(adev->adm_lib, "adm_deinit");
10340 adev->adm_register_input_stream = (adm_register_input_stream_t)
10341 dlsym(adev->adm_lib, "adm_register_input_stream");
10342 adev->adm_register_output_stream = (adm_register_output_stream_t)
10343 dlsym(adev->adm_lib, "adm_register_output_stream");
10344 adev->adm_deregister_stream = (adm_deregister_stream_t)
10345 dlsym(adev->adm_lib, "adm_deregister_stream");
10346 adev->adm_request_focus = (adm_request_focus_t)
10347 dlsym(adev->adm_lib, "adm_request_focus");
10348 adev->adm_abandon_focus = (adm_abandon_focus_t)
10349 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010350 adev->adm_set_config = (adm_set_config_t)
10351 dlsym(adev->adm_lib, "adm_set_config");
10352 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10353 dlsym(adev->adm_lib, "adm_request_focus_v2");
10354 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10355 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10356 adev->adm_on_routing_change = (adm_on_routing_change_t)
10357 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010358 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10359 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010360 }
10361 }
10362
Aalique Grahame22e49102018-12-18 14:23:57 -080010363 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010364 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010365 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010366 //initialize this to false for now,
10367 //this will be set to true through set param
10368 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010369
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010370 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010371 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010372
10373 if (k_enable_extended_precision)
10374 adev_verify_devices(adev);
10375
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010376 adev->dsp_bit_width_enforce_mode =
10377 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010378
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010379 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10380 &adev->streams_output_cfg_list,
10381 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010382
Kiran Kandi910e1862013-10-29 13:29:42 -070010383 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010384
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010385 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -080010386 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
10387 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010388 trial = atoi(value);
10389 if (period_size_is_plausible_for_low_latency(trial)) {
10390 pcm_config_low_latency.period_size = trial;
10391 pcm_config_low_latency.start_threshold = trial / 4;
10392 pcm_config_low_latency.avail_min = trial / 4;
10393 configured_low_latency_capture_period_size = trial;
10394 }
10395 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010396 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10397 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010398 trial = atoi(value);
10399 if (period_size_is_plausible_for_low_latency(trial)) {
10400 configured_low_latency_capture_period_size = trial;
10401 }
10402 }
10403
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010404 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10405
Eric Laurent4b084132018-10-19 17:33:43 -070010406 adev->camera_orientation = CAMERA_DEFAULT;
10407
Aalique Grahame22e49102018-12-18 14:23:57 -080010408 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
10409 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010410 af_period_multiplier = atoi(value);
10411 if (af_period_multiplier < 0)
10412 af_period_multiplier = 2;
10413 else if (af_period_multiplier > 4)
10414 af_period_multiplier = 4;
10415
10416 ALOGV("new period_multiplier = %d", af_period_multiplier);
10417 }
10418
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010419 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010420
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010421 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010422 pthread_mutex_unlock(&adev_init_lock);
10423
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010424 if (adev->adm_init)
10425 adev->adm_data = adev->adm_init();
10426
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010427 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010428 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010429 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010430
10431 audio_extn_snd_mon_init();
10432 pthread_mutex_lock(&adev->lock);
10433 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10434 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010435 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10436 /*
10437 * if the battery state callback happens before charging can be queried,
10438 * it will be guarded with the adev->lock held in the cb function and so
10439 * the callback value will reflect the latest state
10440 */
10441 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010442 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010443 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010444 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010445 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010446 /* Allocate memory for Device config params */
10447 adev->device_cfg_params = (struct audio_device_config_param*)
10448 calloc(platform_get_max_codec_backend(),
10449 sizeof(struct audio_device_config_param));
10450 if (adev->device_cfg_params == NULL)
10451 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010452
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010453 /*
10454 * Check if new PSPD matrix mixer control is supported. If not
10455 * supported, then set flag so that old mixer ctrl is sent while
10456 * sending pspd coefficients on older kernel version. Query mixer
10457 * control for default pcm id and channel value one.
10458 */
10459 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10460 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10461
10462 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10463 if (!ctl) {
10464 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10465 __func__, mixer_ctl_name);
10466 adev->use_old_pspd_mix_ctrl = true;
10467 }
10468
Eric Laurent994a6932013-07-17 11:51:42 -070010469 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010470 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010471
10472adev_open_err:
10473 free_map(adev->patch_map);
10474 free_map(adev->io_streams_map);
10475 if (adev->snd_dev_ref_cnt)
10476 free(adev->snd_dev_ref_cnt);
10477 pthread_mutex_destroy(&adev->lock);
10478 free(adev);
10479 adev = NULL;
10480 *device = NULL;
10481 pthread_mutex_unlock(&adev_init_lock);
10482 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010483}
10484
10485static struct hw_module_methods_t hal_module_methods = {
10486 .open = adev_open,
10487};
10488
10489struct audio_module HAL_MODULE_INFO_SYM = {
10490 .common = {
10491 .tag = HARDWARE_MODULE_TAG,
10492 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10493 .hal_api_version = HARDWARE_HAL_API_VERSION,
10494 .id = AUDIO_HARDWARE_MODULE_ID,
10495 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010496 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010497 .methods = &hal_module_methods,
10498 },
10499};