blob: 18384fbc1bb4668d74e79969925eb0c9482ef23e [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
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800685static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700686 audio_patch_handle_t patch_handle)
687{
688 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
689 return;
690
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700691 struct audio_patch_info *p_info =
692 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
693 if (p_info) {
694 ALOGV("%s: Remove patch %d", __func__, patch_handle);
695 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
696 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700697 free(p_info);
698 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700699}
700
701static inline int io_streams_map_insert(struct audio_device *adev,
702 struct audio_stream *stream,
703 audio_io_handle_t handle,
704 audio_patch_handle_t patch_handle)
705{
706 struct audio_stream_info *s_info =
707 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
708
709 if (s_info == NULL) {
710 ALOGE("%s: Could not allocate stream info", __func__);
711 return -ENOMEM;
712 }
713 s_info->stream = stream;
714 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700715
716 pthread_mutex_lock(&adev->lock);
717 struct audio_stream_info *stream_info =
718 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700719 if (stream_info != NULL)
720 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800721 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700722 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
723 return 0;
724}
725
726static inline void io_streams_map_remove(struct audio_device *adev,
727 audio_io_handle_t handle)
728{
729 pthread_mutex_lock(&adev->lock);
730 struct audio_stream_info *s_info =
731 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700732 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800733 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700734 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800735 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700736 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800737done:
738 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700739 return;
740}
741
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800742static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 audio_patch_handle_t handle)
744{
745 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700746 p_info = (struct audio_patch_info *)
747 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700748 return p_info;
749}
750
vivek mehtaa76401a2015-04-24 14:12:15 -0700751__attribute__ ((visibility ("default")))
752bool audio_hw_send_gain_dep_calibration(int level) {
753 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700754 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700755
756 pthread_mutex_lock(&adev_init_lock);
757
758 if (adev != NULL && adev->platform != NULL) {
759 pthread_mutex_lock(&adev->lock);
760 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700761
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530762 // cache level info for any of the use case which
763 // was not started.
764 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700765
vivek mehtaa76401a2015-04-24 14:12:15 -0700766 pthread_mutex_unlock(&adev->lock);
767 } else {
768 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
769 }
770
771 pthread_mutex_unlock(&adev_init_lock);
772
773 return ret_val;
774}
775
Ashish Jain5106d362016-05-11 19:23:33 +0530776static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
777{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800778 bool gapless_enabled = false;
779 const char *mixer_ctl_name = "Compress Gapless Playback";
780 struct mixer_ctl *ctl;
781
782 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700783 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530784
785 /*Disable gapless if its AV playback*/
786 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800787
788 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
789 if (!ctl) {
790 ALOGE("%s: Could not get ctl for mixer cmd - %s",
791 __func__, mixer_ctl_name);
792 return -EINVAL;
793 }
794
795 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
796 ALOGE("%s: Could not set gapless mode %d",
797 __func__, gapless_enabled);
798 return -EINVAL;
799 }
800 return 0;
801}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700802
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700803__attribute__ ((visibility ("default")))
804int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
805 int table_size) {
806 int ret_val = 0;
807 ALOGV("%s: enter ... ", __func__);
808
809 pthread_mutex_lock(&adev_init_lock);
810 if (adev == NULL) {
811 ALOGW("%s: adev is NULL .... ", __func__);
812 goto done;
813 }
814
815 pthread_mutex_lock(&adev->lock);
816 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
817 pthread_mutex_unlock(&adev->lock);
818done:
819 pthread_mutex_unlock(&adev_init_lock);
820 ALOGV("%s: exit ... ", __func__);
821 return ret_val;
822}
823
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800824bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800825{
826 bool ret = false;
827 ALOGV("%s: enter ...", __func__);
828
829 pthread_mutex_lock(&adev_init_lock);
830
831 if (adev != NULL && adev->platform != NULL) {
832 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800833 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800834 pthread_mutex_unlock(&adev->lock);
835 }
836
837 pthread_mutex_unlock(&adev_init_lock);
838
839 ALOGV("%s: exit with ret %d", __func__, ret);
840 return ret;
841}
Aalique Grahame22e49102018-12-18 14:23:57 -0800842
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700843static bool is_supported_format(audio_format_t format)
844{
Eric Laurent86e17132013-09-12 17:49:30 -0700845 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530846 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530847 format == AUDIO_FORMAT_AAC_LC ||
848 format == AUDIO_FORMAT_AAC_HE_V1 ||
849 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530850 format == AUDIO_FORMAT_AAC_ADTS_LC ||
851 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
852 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530853 format == AUDIO_FORMAT_AAC_LATM_LC ||
854 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
855 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530856 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
857 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530858 format == AUDIO_FORMAT_PCM_FLOAT ||
859 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700860 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530861 format == AUDIO_FORMAT_AC3 ||
862 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700863 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530864 format == AUDIO_FORMAT_DTS ||
865 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800866 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530867 format == AUDIO_FORMAT_ALAC ||
868 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530869 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530870 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800871 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530872 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700873 format == AUDIO_FORMAT_APTX ||
874 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800875 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700876
877 return false;
878}
879
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700880static inline bool is_mmap_usecase(audio_usecase_t uc_id)
881{
882 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
883 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
884}
885
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700886static inline bool is_valid_volume(float left, float right)
887{
888 return ((left >= 0.0f && right >= 0.0f) ? true : false);
889}
890
Avinash Vaish71a8b972014-07-24 15:36:33 +0530891static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
892 struct audio_usecase *uc_info)
893{
894 struct listnode *node;
895 struct audio_usecase *usecase;
896
897 if (uc_info == NULL)
898 return -EINVAL;
899
900 /* Re-route all voice usecases on the shared backend other than the
901 specified usecase to new snd devices */
902 list_for_each(node, &adev->usecase_list) {
903 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800904 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530905 enable_audio_route(adev, usecase);
906 }
907 return 0;
908}
909
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530910static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530911{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530912 ALOGV("%s", __func__);
913 audio_route_apply_and_update_path(adev->audio_route,
914 "asrc-mode");
915 adev->asrc_mode_enabled = true;
916}
917
918static void disable_asrc_mode(struct audio_device *adev)
919{
920 ALOGV("%s", __func__);
921 audio_route_reset_and_update_path(adev->audio_route,
922 "asrc-mode");
923 adev->asrc_mode_enabled = false;
924}
925
926/*
927 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
928 * 44.1 or Native DSD backends are enabled for any of current use case.
929 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
930 * - Disable current mix path use case(Headphone backend) and re-enable it with
931 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
932 * e.g. Naitve DSD or Headphone 44.1 -> + 48
933 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530934static void check_and_set_asrc_mode(struct audio_device *adev,
935 struct audio_usecase *uc_info,
936 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530937{
938 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530939 int i, num_new_devices = 0;
940 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
941 /*
942 *Split snd device for new combo use case
943 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
944 */
945 if (platform_split_snd_device(adev->platform,
946 snd_device,
947 &num_new_devices,
948 split_new_snd_devices) == 0) {
949 for (i = 0; i < num_new_devices; i++)
950 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
951 } else {
952 int new_backend_idx = platform_get_backend_index(snd_device);
953 if (((new_backend_idx == HEADPHONE_BACKEND) ||
954 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
955 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
956 !adev->asrc_mode_enabled) {
957 struct listnode *node = NULL;
958 struct audio_usecase *uc = NULL;
959 struct stream_out *curr_out = NULL;
960 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
961 int i, num_devices, ret = 0;
962 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530963
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530964 list_for_each(node, &adev->usecase_list) {
965 uc = node_to_item(node, struct audio_usecase, list);
966 curr_out = (struct stream_out*) uc->stream.out;
967 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
968 /*
969 *Split snd device for existing combo use case
970 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
971 */
972 ret = platform_split_snd_device(adev->platform,
973 uc->out_snd_device,
974 &num_devices,
975 split_snd_devices);
976 if (ret < 0 || num_devices == 0) {
977 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
978 split_snd_devices[0] = uc->out_snd_device;
979 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800980 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530981 for (i = 0; i < num_devices; i++) {
982 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
983 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
984 if((new_backend_idx == HEADPHONE_BACKEND) &&
985 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
986 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
987 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
988 __func__);
989 enable_asrc_mode(adev);
990 break;
991 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
992 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
993 (usecase_backend_idx == HEADPHONE_BACKEND)) {
994 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
995 __func__);
996 disable_audio_route(adev, uc);
997 disable_snd_device(adev, uc->out_snd_device);
998 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
999 if (new_backend_idx == DSD_NATIVE_BACKEND)
1000 audio_route_apply_and_update_path(adev->audio_route,
1001 "hph-true-highquality-mode");
1002 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1003 (curr_out->bit_width >= 24))
1004 audio_route_apply_and_update_path(adev->audio_route,
1005 "hph-highquality-mode");
1006 enable_asrc_mode(adev);
1007 enable_snd_device(adev, uc->out_snd_device);
1008 enable_audio_route(adev, uc);
1009 break;
1010 }
1011 }
1012 // reset split devices count
1013 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001014 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301015 if (adev->asrc_mode_enabled)
1016 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301017 }
1018 }
1019 }
1020}
1021
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001022static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1023 struct audio_effect_config effect_config,
1024 unsigned int param_value)
1025{
1026 char mixer_ctl_name[] = "Audio Effect";
1027 struct mixer_ctl *ctl;
1028 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001029 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001030
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001031 if (in == NULL) {
1032 ALOGE("%s: active input stream is NULL", __func__);
1033 return -EINVAL;
1034 }
1035
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001036 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1037 if (!ctl) {
1038 ALOGE("%s: Could not get mixer ctl - %s",
1039 __func__, mixer_ctl_name);
1040 return -EINVAL;
1041 }
1042
1043 set_values[0] = 1; //0:Rx 1:Tx
1044 set_values[1] = in->app_type_cfg.app_type;
1045 set_values[2] = (long)effect_config.module_id;
1046 set_values[3] = (long)effect_config.instance_id;
1047 set_values[4] = (long)effect_config.param_id;
1048 set_values[5] = param_value;
1049
1050 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1051
1052 return 0;
1053
1054}
1055
1056static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1057 int effect_type, unsigned int *param_value)
1058{
1059 int ret = 0;
1060 struct audio_effect_config other_effect_config;
1061 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001062 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001063
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001064 if (in == NULL) {
1065 ALOGE("%s: active input stream is NULL", __func__);
1066 return -EINVAL;
1067 }
1068
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001069 usecase = get_usecase_from_list(adev, in->usecase);
1070 if (!usecase)
1071 return -EINVAL;
1072
1073 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1074 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1075 if (ret < 0) {
1076 ALOGE("%s Failed to get effect params %d", __func__, ret);
1077 return ret;
1078 }
1079
1080 if (module_id == other_effect_config.module_id) {
1081 //Same module id for AEC/NS. Values need to be combined
1082 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1083 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1084 *param_value |= other_effect_config.param_value;
1085 }
1086 }
1087
1088 return ret;
1089}
1090
1091static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301092{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001093 struct audio_effect_config effect_config;
1094 struct audio_usecase *usecase = NULL;
1095 int ret = 0;
1096 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001097 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001098
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001099 if(!voice_extn_is_dynamic_ecns_enabled())
1100 return ENOSYS;
1101
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001102 if (!in) {
1103 ALOGE("%s: Invalid input stream", __func__);
1104 return -EINVAL;
1105 }
1106
1107 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1108
1109 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001110 if (usecase == NULL) {
1111 ALOGE("%s: Could not find the usecase (%d) in the list",
1112 __func__, in->usecase);
1113 return -EINVAL;
1114 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001115
1116 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1117 if (ret < 0) {
1118 ALOGE("%s Failed to get module id %d", __func__, ret);
1119 return ret;
1120 }
1121 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1122 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1123
1124 if(enable)
1125 param_value = effect_config.param_value;
1126
1127 /*Special handling for AEC & NS effects Param values need to be
1128 updated if module ids are same*/
1129
1130 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1131 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1132 if (ret < 0)
1133 return ret;
1134 }
1135
1136 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1137
1138 return ret;
1139}
1140
1141static void check_and_enable_effect(struct audio_device *adev)
1142{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001143 if(!voice_extn_is_dynamic_ecns_enabled())
1144 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001145
Eric Laurent637e2d42018-11-15 12:24:31 -08001146 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001147
Eric Laurent637e2d42018-11-15 12:24:31 -08001148 if (in != NULL && !in->standby) {
1149 if (in->enable_aec)
1150 enable_disable_effect(adev, EFFECT_AEC, true);
1151
1152 if (in->enable_ns &&
1153 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1154 enable_disable_effect(adev, EFFECT_NS, true);
1155 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001156 }
1157}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001158
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001159int pcm_ioctl(struct pcm *pcm, int request, ...)
1160{
1161 va_list ap;
1162 void * arg;
1163 int pcm_fd = *(int*)pcm;
1164
1165 va_start(ap, request);
1166 arg = va_arg(ap, void *);
1167 va_end(ap);
1168
1169 return ioctl(pcm_fd, request, arg);
1170}
1171
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001172int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001173 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001174{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001175 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001176 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301177 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301178 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001179 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301180 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001181
1182 if (usecase == NULL)
1183 return -EINVAL;
1184
1185 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1186
Carter Hsu2e429db2019-05-14 18:50:52 +08001187 if (usecase->type == PCM_CAPTURE) {
1188 struct stream_in *in = usecase->stream.in;
1189 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001190 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001191
1192 if (in) {
1193 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001194 list_init(&out_devices);
1195 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001196 struct listnode *node;
1197 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1198 USECASE_AUDIO_PLAYBACK_VOIP);
1199 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001200 assign_devices(&out_devices,
1201 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001202 } else if (adev->primary_output &&
1203 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001204 assign_devices(&out_devices,
1205 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001206 } else {
1207 list_for_each(node, &adev->usecase_list) {
1208 uinfo = node_to_item(node, struct audio_usecase, list);
1209 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001210 assign_devices(&out_devices,
1211 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001212 break;
1213 }
1214 }
1215 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001216
1217 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001218 in->ec_opened = true;
1219 }
1220 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001221 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1222 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1223 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001224 snd_device = usecase->in_snd_device;
1225 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001227 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001228
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001229#ifdef DS1_DOLBY_DAP_ENABLED
1230 audio_extn_dolby_set_dmid(adev);
1231 audio_extn_dolby_set_endpoint(adev);
1232#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001233 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001234 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301235 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001236 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001237 if (audio_extn_is_maxx_audio_enabled())
1238 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301239 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301240 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1241 out = usecase->stream.out;
1242 if (out && out->compr)
1243 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1244 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301245
1246 if (usecase->type == PCM_CAPTURE) {
1247 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001248 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301249 ALOGD("%s: set custom mtmx params v1", __func__);
1250 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1251 }
1252 } else {
1253 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1254 }
Manish Dewangan58229382017-02-02 15:48:41 +05301255
Andy Hung756ecc12018-10-19 17:47:12 -07001256 // we shouldn't truncate mixer_path
1257 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1258 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1259 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001260 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001261 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301262 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1263 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1264 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1265 if (parms) {
1266 audio_extn_fm_set_parameters(adev, parms);
1267 str_parms_destroy(parms);
1268 }
1269 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270 ALOGV("%s: exit", __func__);
1271 return 0;
1272}
1273
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001274int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001275 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001276{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001278 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301279 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001280
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301281 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001282 return -EINVAL;
1283
1284 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301285 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001286 snd_device = usecase->in_snd_device;
1287 else
1288 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001289 // we shouldn't truncate mixer_path
1290 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1291 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1292 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001293 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001294 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001295 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001296 if (usecase->type == PCM_CAPTURE) {
1297 struct stream_in *in = usecase->stream.in;
1298 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001299 struct listnode out_devices;
1300 list_init(&out_devices);
1301 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001302 in->ec_opened = false;
1303 }
1304 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001305 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301306 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301307
1308 if (usecase->type == PCM_CAPTURE) {
1309 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001310 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301311 ALOGD("%s: reset custom mtmx params v1", __func__);
1312 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1313 }
1314 } else {
1315 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1316 }
1317
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001318 if ((usecase->type == PCM_PLAYBACK) &&
1319 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301320 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001322 ALOGV("%s: exit", __func__);
1323 return 0;
1324}
1325
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001326int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001327 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001328{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301329 int i, num_devices = 0;
1330 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001331 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1332
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001333 if (snd_device < SND_DEVICE_MIN ||
1334 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001335 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001336 return -EINVAL;
1337 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001338
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001339 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001340 ALOGE("%s: Invalid sound device returned", __func__);
1341 return -EINVAL;
1342 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001343
1344 adev->snd_dev_ref_cnt[snd_device]++;
1345
1346 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1347 (platform_split_snd_device(adev->platform,
1348 snd_device,
1349 &num_devices,
1350 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001351 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001352 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001353 return 0;
1354 }
1355
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001356 if (audio_extn_spkr_prot_is_enabled())
1357 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001358
Aalique Grahame22e49102018-12-18 14:23:57 -08001359 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1360
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001361 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1362 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001363 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1364 goto err;
1365 }
1366 audio_extn_dev_arbi_acquire(snd_device);
1367 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001368 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001369 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001370 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001371 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001372 } else if (platform_split_snd_device(adev->platform,
1373 snd_device,
1374 &num_devices,
1375 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301376 for (i = 0; i < num_devices; i++) {
1377 enable_snd_device(adev, new_snd_devices[i]);
1378 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001379 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001380 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001381 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301382
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301383
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001384 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1385 (audio_extn_a2dp_start_playback() < 0)) {
1386 ALOGE(" fail to configure A2dp Source control path ");
1387 goto err;
1388 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001389
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001390 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1391 (audio_extn_a2dp_start_capture() < 0)) {
1392 ALOGE(" fail to configure A2dp Sink control path ");
1393 goto err;
1394 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301395
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001396 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1397 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1398 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1399 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1400 ALOGE(" fail to configure sco control path ");
1401 goto err;
1402 }
Zhou Song12c29502019-03-16 10:37:18 +08001403 }
1404
Zhou Song331c8e52019-08-26 14:16:12 +08001405 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001406 /* due to the possibility of calibration overwrite between listen
1407 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001408 audio_extn_sound_trigger_update_device_status(snd_device,
1409 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301410 audio_extn_listen_update_device_status(snd_device,
1411 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001412 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001413 audio_extn_sound_trigger_update_device_status(snd_device,
1414 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301415 audio_extn_listen_update_device_status(snd_device,
1416 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001417 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001418 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001419 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001420 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301421
1422 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1423 !adev->native_playback_enabled &&
1424 audio_is_true_native_stream_active(adev)) {
1425 ALOGD("%s: %d: napb: enabling native mode in hardware",
1426 __func__, __LINE__);
1427 audio_route_apply_and_update_path(adev->audio_route,
1428 "true-native-mode");
1429 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301430 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301431 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1432 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001433 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001434 ALOGD("%s: init ec ref loopback", __func__);
1435 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1436 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001437 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001439err:
1440 adev->snd_dev_ref_cnt[snd_device]--;
1441 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442}
1443
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001444int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001445 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301447 int i, num_devices = 0;
1448 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001449 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1450
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001451 if (snd_device < SND_DEVICE_MIN ||
1452 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001453 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001454 return -EINVAL;
1455 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001456
1457 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1458 ALOGE("%s: Invalid sound device returned", __func__);
1459 return -EINVAL;
1460 }
1461
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1463 ALOGE("%s: device ref cnt is already 0", __func__);
1464 return -EINVAL;
1465 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001466
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001468
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001469
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001470 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001471 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301472
Aalique Grahame22e49102018-12-18 14:23:57 -08001473 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1474
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001475 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1476 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001477 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001478
1479 // when speaker device is disabled, reset swap.
1480 // will be renabled on usecase start
1481 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001482 } else if (platform_split_snd_device(adev->platform,
1483 snd_device,
1484 &num_devices,
1485 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301486 for (i = 0; i < num_devices; i++) {
1487 disable_snd_device(adev, new_snd_devices[i]);
1488 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001489 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001490 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001491 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001492 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001493
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001494 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301495 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001496 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001497 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001498 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001499 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301500 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001501 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301502 adev->native_playback_enabled) {
1503 ALOGD("%s: %d: napb: disabling native mode in hardware",
1504 __func__, __LINE__);
1505 audio_route_reset_and_update_path(adev->audio_route,
1506 "true-native-mode");
1507 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001508 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301509 adev->asrc_mode_enabled) {
1510 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301511 disable_asrc_mode(adev);
1512 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001513 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301514 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001515 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001516 ALOGD("%s: deinit ec ref loopback", __func__);
1517 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1518 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001519
1520 audio_extn_utils_release_snd_device(snd_device);
1521 } else {
1522 if (platform_split_snd_device(adev->platform,
1523 snd_device,
1524 &num_devices,
1525 new_snd_devices) == 0) {
1526 for (i = 0; i < num_devices; i++) {
1527 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1528 }
1529 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001530 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 return 0;
1533}
1534
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001535/*
1536 legend:
1537 uc - existing usecase
1538 new_uc - new usecase
1539 d1, d11, d2 - SND_DEVICE enums
1540 a1, a2 - corresponding ANDROID device enums
1541 B1, B2 - backend strings
1542
1543case 1
1544 uc->dev d1 (a1) B1
1545 new_uc->dev d1 (a1), d2 (a2) B1, B2
1546
1547 resolution: disable and enable uc->dev on d1
1548
1549case 2
1550 uc->dev d1 (a1) B1
1551 new_uc->dev d11 (a1) B1
1552
1553 resolution: need to switch uc since d1 and d11 are related
1554 (e.g. speaker and voice-speaker)
1555 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1556
1557case 3
1558 uc->dev d1 (a1) B1
1559 new_uc->dev d2 (a2) B2
1560
1561 resolution: no need to switch uc
1562
1563case 4
1564 uc->dev d1 (a1) B1
1565 new_uc->dev d2 (a2) B1
1566
1567 resolution: disable enable uc-dev on d2 since backends match
1568 we cannot enable two streams on two different devices if they
1569 share the same backend. e.g. if offload is on speaker device using
1570 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1571 using the same backend, offload must also be switched to voice-handset.
1572
1573case 5
1574 uc->dev d1 (a1) B1
1575 new_uc->dev d1 (a1), d2 (a2) B1
1576
1577 resolution: disable enable uc-dev on d2 since backends match
1578 we cannot enable two streams on two different devices if they
1579 share the same backend.
1580
1581case 6
1582 uc->dev d1 (a1) B1
1583 new_uc->dev d2 (a1) B2
1584
1585 resolution: no need to switch
1586
1587case 7
1588 uc->dev d1 (a1), d2 (a2) B1, B2
1589 new_uc->dev d1 (a1) B1
1590
1591 resolution: no need to switch
1592
Zhou Song4ba65882018-07-09 14:48:07 +08001593case 8
1594 uc->dev d1 (a1) B1
1595 new_uc->dev d11 (a1), d2 (a2) B1, B2
1596 resolution: compared to case 1, for this case, d1 and d11 are related
1597 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001598*/
1599static snd_device_t derive_playback_snd_device(void * platform,
1600 struct audio_usecase *uc,
1601 struct audio_usecase *new_uc,
1602 snd_device_t new_snd_device)
1603{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001604 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001605
1606 snd_device_t d1 = uc->out_snd_device;
1607 snd_device_t d2 = new_snd_device;
1608
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001609 list_init(&a1);
1610 list_init(&a2);
1611
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301612 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301613 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001614 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1615 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301616 break;
1617 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001618 assign_devices(&a1, &uc->stream.out->device_list);
1619 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301620 break;
1621 }
1622
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001623 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001624 if (!compare_devices(&a1, &a2) &&
1625 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001626 snd_device_t d3[2];
1627 int num_devices = 0;
1628 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001629 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001630 &num_devices,
1631 d3);
1632 if (ret < 0) {
1633 if (ret != -ENOSYS) {
1634 ALOGW("%s failed to split snd_device %d",
1635 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001636 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001637 }
1638 goto end;
1639 }
1640
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001641 if (platform_check_backends_match(d3[0], d3[1])) {
1642 return d2; // case 5
1643 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001644 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301645 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001646 // check if d1 is related to any of d3's
1647 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001648 return d1; // case 1
1649 else
1650 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001651 }
1652 } else {
1653 if (platform_check_backends_match(d1, d2)) {
1654 return d2; // case 2, 4
1655 } else {
1656 return d1; // case 6, 3
1657 }
1658 }
1659
1660end:
1661 return d2; // return whatever was calculated before.
1662}
1663
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001664static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301665 struct audio_usecase *uc_info,
1666 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001667{
1668 struct listnode *node;
1669 struct audio_usecase *usecase;
1670 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301671 snd_device_t uc_derive_snd_device;
1672 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001673 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1674 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001675 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301676 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001677 /*
1678 * This function is to make sure that all the usecases that are active on
1679 * the hardware codec backend are always routed to any one device that is
1680 * handled by the hardware codec.
1681 * For example, if low-latency and deep-buffer usecases are currently active
1682 * on speaker and out_set_parameters(headset) is received on low-latency
1683 * output, then we have to make sure deep-buffer is also switched to headset,
1684 * because of the limitation that both the devices cannot be enabled
1685 * at the same time as they share the same backend.
1686 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001687 /*
1688 * This call is to check if we need to force routing for a particular stream
1689 * If there is a backend configuration change for the device when a
1690 * new stream starts, then ADM needs to be closed and re-opened with the new
1691 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001692 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001693 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001694 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1695 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301696 /* For a2dp device reconfigure all active sessions
1697 * with new AFE encoder format based on a2dp state
1698 */
1699 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1700 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1701 audio_extn_a2dp_is_force_device_switch()) {
1702 force_routing = true;
1703 force_restart_session = true;
1704 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301705 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1706
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001707 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001708 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001709 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001710 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1711 switch_device[i] = false;
1712
1713 list_for_each(node, &adev->usecase_list) {
1714 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001715
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301716 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1717 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301718 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301719 platform_get_snd_device_name(usecase->out_snd_device),
1720 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301721 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1722 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301723 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1724 usecase, uc_info, snd_device);
1725 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001726 (is_codec_backend_out_device_type(&usecase->device_list) ||
1727 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1728 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1729 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1730 is_a2dp_out_device_type(&usecase->device_list) ||
1731 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301732 ((force_restart_session) ||
1733 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301734 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1735 __func__, use_case_table[usecase->id],
1736 platform_get_snd_device_name(usecase->out_snd_device));
1737 disable_audio_route(adev, usecase);
1738 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301739 /* Enable existing usecase on derived playback device */
1740 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301741 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301742 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001743 }
1744 }
1745
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301746 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1747 num_uc_to_switch);
1748
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001749 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001750 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001751
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301752 /* Make sure the previous devices to be disabled first and then enable the
1753 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001754 list_for_each(node, &adev->usecase_list) {
1755 usecase = node_to_item(node, struct audio_usecase, list);
1756 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001757 /* Check if output sound device to be switched can be split and if any
1758 of the split devices match with derived sound device */
1759 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1760 &num_devices, split_snd_devices) == 0) {
1761 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1762 for (i = 0; i < num_devices; i++) {
1763 /* Disable devices that do not match with derived sound device */
1764 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1765 disable_snd_device(adev, split_snd_devices[i]);
1766 }
1767 } else {
1768 disable_snd_device(adev, usecase->out_snd_device);
1769 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001770 }
1771 }
1772
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001773 list_for_each(node, &adev->usecase_list) {
1774 usecase = node_to_item(node, struct audio_usecase, list);
1775 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001776 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1777 &num_devices, split_snd_devices) == 0) {
1778 /* Enable derived sound device only if it does not match with
1779 one of the split sound devices. This is because the matching
1780 sound device was not disabled */
1781 bool should_enable = true;
1782 for (i = 0; i < num_devices; i++) {
1783 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1784 should_enable = false;
1785 break;
1786 }
1787 }
1788 if (should_enable)
1789 enable_snd_device(adev, derive_snd_device[usecase->id]);
1790 } else {
1791 enable_snd_device(adev, derive_snd_device[usecase->id]);
1792 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001793 }
1794 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001796 /* Re-route all the usecases on the shared backend other than the
1797 specified usecase to new snd devices */
1798 list_for_each(node, &adev->usecase_list) {
1799 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301800 /* Update the out_snd_device only before enabling the audio route */
1801 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301802 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301803 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301804 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301805 use_case_table[usecase->id],
1806 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001807 /* Update voc calibration before enabling VoIP route */
1808 if (usecase->type == VOIP_CALL)
1809 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001810 usecase->out_snd_device,
1811 platform_get_input_snd_device(
1812 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301813 &uc_info->device_list,
1814 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301815 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301816 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001817 out_set_voip_volume(&usecase->stream.out->stream,
1818 usecase->stream.out->volume_l,
1819 usecase->stream.out->volume_r);
1820 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301821 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822 }
1823 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001824 }
1825}
1826
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301827static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001828 struct audio_usecase *uc_info,
1829 snd_device_t snd_device)
1830{
1831 struct listnode *node;
1832 struct audio_usecase *usecase;
1833 bool switch_device[AUDIO_USECASE_MAX];
1834 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001835 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001836 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001837
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301838 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1839 snd_device);
1840 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301841
1842 /*
1843 * Make sure out devices is checked against out codec backend device and
1844 * also in devices against in codec backend. Checking out device against in
1845 * codec backend or vice versa causes issues.
1846 */
1847 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001848 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001849 /*
1850 * This function is to make sure that all the active capture usecases
1851 * are always routed to the same input sound device.
1852 * For example, if audio-record and voice-call usecases are currently
1853 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1854 * is received for voice call then we have to make sure that audio-record
1855 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1856 * because of the limitation that two devices cannot be enabled
1857 * at the same time if they share the same backend.
1858 */
1859 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1860 switch_device[i] = false;
1861
1862 list_for_each(node, &adev->usecase_list) {
1863 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301864 /*
1865 * TODO: Enhance below condition to handle BT sco/USB multi recording
1866 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301867
1868 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1869 (usecase->in_snd_device != snd_device || force_routing));
1870 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1871 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1872 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001873 ((backend_check_cond &&
1874 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001875 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001876 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001877 is_single_device_type_equal(&usecase->device_list,
1878 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001879 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001880 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001881 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301882 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001883 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001884 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001885 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001886 switch_device[usecase->id] = true;
1887 num_uc_to_switch++;
1888 }
1889 }
1890
1891 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001892 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001893
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301894 /* Make sure the previous devices to be disabled first and then enable the
1895 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001896 list_for_each(node, &adev->usecase_list) {
1897 usecase = node_to_item(node, struct audio_usecase, list);
1898 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001899 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001900 }
1901 }
1902
1903 list_for_each(node, &adev->usecase_list) {
1904 usecase = node_to_item(node, struct audio_usecase, list);
1905 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001906 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001907 }
1908 }
1909
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001910 /* Re-route all the usecases on the shared backend other than the
1911 specified usecase to new snd devices */
1912 list_for_each(node, &adev->usecase_list) {
1913 usecase = node_to_item(node, struct audio_usecase, list);
1914 /* Update the in_snd_device only before enabling the audio route */
1915 if (switch_device[usecase->id] ) {
1916 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001917 if (usecase->type != VOICE_CALL) {
1918 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301919 if (usecase->type == VOIP_CALL) {
1920 snd_device_t voip_snd_device;
1921 voip_snd_device = platform_get_output_snd_device(adev->platform,
1922 uc_info->stream.out,
1923 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08001924 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301925 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08001926 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05301927 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05301928 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001929 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001930 }
1931 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001932 }
1933}
1934
Mingming Yin3a941d42016-02-17 18:08:05 -08001935static void reset_hdmi_sink_caps(struct stream_out *out) {
1936 int i = 0;
1937
1938 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1939 out->supported_channel_masks[i] = 0;
1940 }
1941 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1942 out->supported_formats[i] = 0;
1943 }
1944 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1945 out->supported_sample_rates[i] = 0;
1946 }
1947}
1948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001950static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951{
Mingming Yin3a941d42016-02-17 18:08:05 -08001952 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001953 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
1954 out->extconn.cs.controller,
1955 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956
Mingming Yin3a941d42016-02-17 18:08:05 -08001957 reset_hdmi_sink_caps(out);
1958
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001959 /* Cache ext disp type */
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08001960 ret = platform_get_ext_disp_type_v2(adev->platform,
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001961 out->extconn.cs.controller,
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08001962 out->extconn.cs.stream);
1963 if(ret < 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001964 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001965 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001966 }
1967
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001970 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001971 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001972 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1973 case 6:
1974 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1975 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1976 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1977 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1978 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1979 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 break;
1981 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001982 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001983 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984 break;
1985 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001986
1987 // check channel format caps
1988 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001989 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
1990 out->extconn.cs.controller,
1991 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08001992 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1993 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1994 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1995 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1996 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1997 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1998 }
1999
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002000 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2001 out->extconn.cs.controller,
2002 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002003 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2004 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2005 }
2006
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002007 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2008 out->extconn.cs.controller,
2009 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002010 ALOGV(":%s HDMI supports DTS format", __func__);
2011 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2012 }
2013
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002014 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2015 out->extconn.cs.controller,
2016 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002017 ALOGV(":%s HDMI supports DTS HD format", __func__);
2018 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2019 }
2020
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002021 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2022 out->extconn.cs.controller,
2023 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002024 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2025 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2026 }
2027
Mingming Yin3a941d42016-02-17 18:08:05 -08002028
2029 // check sample rate caps
2030 i = 0;
2031 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002032 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2033 out->extconn.cs.controller,
2034 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002035 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2036 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2037 }
2038 }
2039
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002040 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041}
2042
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002043static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2044 uint32_t *supported_sample_rates __unused,
2045 uint32_t max_rates __unused)
2046{
2047 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2048 supported_sample_rates,
2049 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302050 ssize_t i = 0;
2051
2052 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002053 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2054 supported_sample_rates[i]);
2055 }
2056 return count;
2057}
2058
2059static inline int read_usb_sup_channel_masks(bool is_playback,
2060 audio_channel_mask_t *supported_channel_masks,
2061 uint32_t max_masks)
2062{
2063 int channels = audio_extn_usb_get_max_channels(is_playback);
2064 int channel_count;
2065 uint32_t num_masks = 0;
2066 if (channels > MAX_HIFI_CHANNEL_COUNT)
2067 channels = MAX_HIFI_CHANNEL_COUNT;
2068
2069 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002070 // start from 2 channels as framework currently doesn't support mono.
2071 if (channels >= FCC_2) {
2072 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2073 }
2074 for (channel_count = FCC_2;
2075 channel_count <= channels && num_masks < max_masks;
2076 ++channel_count) {
2077 supported_channel_masks[num_masks++] =
2078 audio_channel_mask_for_index_assignment_from_count(channel_count);
2079 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002080 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002081 // For capture we report all supported channel masks from 1 channel up.
2082 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002083 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2084 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002085 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2086 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2087 if (channel_count <= FCC_2) {
2088 mask = audio_channel_in_mask_from_count(channel_count);
2089 supported_channel_masks[num_masks++] = mask;
2090 }
2091 const audio_channel_mask_t index_mask =
2092 audio_channel_mask_for_index_assignment_from_count(channel_count);
2093 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2094 supported_channel_masks[num_masks++] = index_mask;
2095 }
2096 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002097 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302098
vincenttewf51c94e2019-05-07 10:28:53 +08002099 for (size_t i = 0; i < num_masks; ++i) {
2100 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2101 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302102 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002103 return num_masks;
2104}
2105
2106static inline int read_usb_sup_formats(bool is_playback __unused,
2107 audio_format_t *supported_formats,
2108 uint32_t max_formats __unused)
2109{
2110 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2111 switch (bitwidth) {
2112 case 24:
2113 // XXX : usb.c returns 24 for s24 and s24_le?
2114 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2115 break;
2116 case 32:
2117 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2118 break;
2119 case 16:
2120 default :
2121 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2122 break;
2123 }
2124 ALOGV("%s: %s supported format %d", __func__,
2125 is_playback ? "P" : "C", bitwidth);
2126 return 1;
2127}
2128
2129static inline int read_usb_sup_params_and_compare(bool is_playback,
2130 audio_format_t *format,
2131 audio_format_t *supported_formats,
2132 uint32_t max_formats,
2133 audio_channel_mask_t *mask,
2134 audio_channel_mask_t *supported_channel_masks,
2135 uint32_t max_masks,
2136 uint32_t *rate,
2137 uint32_t *supported_sample_rates,
2138 uint32_t max_rates) {
2139 int ret = 0;
2140 int num_formats;
2141 int num_masks;
2142 int num_rates;
2143 int i;
2144
2145 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2146 max_formats);
2147 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2148 max_masks);
2149
2150 num_rates = read_usb_sup_sample_rates(is_playback,
2151 supported_sample_rates, max_rates);
2152
2153#define LUT(table, len, what, dflt) \
2154 for (i=0; i<len && (table[i] != what); i++); \
2155 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2156
2157 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2158 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2159 LUT(supported_sample_rates, num_rates, *rate, 0);
2160
2161#undef LUT
2162 return ret < 0 ? -EINVAL : 0; // HACK TBD
2163}
2164
Alexy Josephb1379942016-01-29 15:49:38 -08002165audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002166 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002167{
2168 struct audio_usecase *usecase;
2169 struct listnode *node;
2170
2171 list_for_each(node, &adev->usecase_list) {
2172 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002173 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002174 ALOGV("%s: usecase id %d", __func__, usecase->id);
2175 return usecase->id;
2176 }
2177 }
2178 return USECASE_INVALID;
2179}
2180
Alexy Josephb1379942016-01-29 15:49:38 -08002181struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002182 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002183{
2184 struct audio_usecase *usecase;
2185 struct listnode *node;
2186
2187 list_for_each(node, &adev->usecase_list) {
2188 usecase = node_to_item(node, struct audio_usecase, list);
2189 if (usecase->id == uc_id)
2190 return usecase;
2191 }
2192 return NULL;
2193}
2194
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302195/*
2196 * is a true native playback active
2197 */
2198bool audio_is_true_native_stream_active(struct audio_device *adev)
2199{
2200 bool active = false;
2201 int i = 0;
2202 struct listnode *node;
2203
2204 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2205 ALOGV("%s:napb: not in true mode or non hdphones device",
2206 __func__);
2207 active = false;
2208 goto exit;
2209 }
2210
2211 list_for_each(node, &adev->usecase_list) {
2212 struct audio_usecase *uc;
2213 uc = node_to_item(node, struct audio_usecase, list);
2214 struct stream_out *curr_out =
2215 (struct stream_out*) uc->stream.out;
2216
2217 if (curr_out && PCM_PLAYBACK == uc->type) {
2218 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2219 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2220 uc->id, curr_out->sample_rate,
2221 curr_out->bit_width,
2222 platform_get_snd_device_name(uc->out_snd_device));
2223
2224 if (is_offload_usecase(uc->id) &&
2225 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2226 active = true;
2227 ALOGD("%s:napb:native stream detected", __func__);
2228 }
2229 }
2230 }
2231exit:
2232 return active;
2233}
2234
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002235uint32_t adev_get_dsp_bit_width_enforce_mode()
2236{
2237 if (adev == NULL) {
2238 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2239 return 0;
2240 }
2241 return adev->dsp_bit_width_enforce_mode;
2242}
2243
2244static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2245{
2246 char value[PROPERTY_VALUE_MAX];
2247 int trial;
2248 uint32_t dsp_bit_width_enforce_mode = 0;
2249
2250 if (!mixer) {
2251 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2252 __func__);
2253 return 0;
2254 }
2255
2256 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2257 value, NULL) > 0) {
2258 trial = atoi(value);
2259 switch (trial) {
2260 case 16:
2261 dsp_bit_width_enforce_mode = 16;
2262 break;
2263 case 24:
2264 dsp_bit_width_enforce_mode = 24;
2265 break;
2266 case 32:
2267 dsp_bit_width_enforce_mode = 32;
2268 break;
2269 default:
2270 dsp_bit_width_enforce_mode = 0;
2271 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2272 break;
2273 }
2274 }
2275
2276 return dsp_bit_width_enforce_mode;
2277}
2278
2279static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2280 uint32_t enforce_mode,
2281 bool enable)
2282{
2283 struct mixer_ctl *ctl = NULL;
2284 const char *mixer_ctl_name = "ASM Bit Width";
2285 uint32_t asm_bit_width_mode = 0;
2286
2287 if (enforce_mode == 0) {
2288 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2289 return;
2290 }
2291
2292 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2293 if (!ctl) {
2294 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2295 __func__, mixer_ctl_name);
2296 return;
2297 }
2298
2299 if (enable)
2300 asm_bit_width_mode = enforce_mode;
2301 else
2302 asm_bit_width_mode = 0;
2303
2304 ALOGV("%s DSP bit width feature status is %d width=%d",
2305 __func__, enable, asm_bit_width_mode);
2306 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2307 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2308 asm_bit_width_mode);
2309
2310 return;
2311}
2312
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302313/*
2314 * if native DSD playback active
2315 */
2316bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2317{
2318 bool active = false;
2319 struct listnode *node = NULL;
2320 struct audio_usecase *uc = NULL;
2321 struct stream_out *curr_out = NULL;
2322
2323 list_for_each(node, &adev->usecase_list) {
2324 uc = node_to_item(node, struct audio_usecase, list);
2325 curr_out = (struct stream_out*) uc->stream.out;
2326
2327 if (curr_out && PCM_PLAYBACK == uc->type &&
2328 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2329 active = true;
2330 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302331 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302332 }
2333 }
2334 return active;
2335}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302336
2337static bool force_device_switch(struct audio_usecase *usecase)
2338{
2339 bool ret = false;
2340 bool is_it_true_mode = false;
2341
Zhou Song30f2c3e2018-02-08 14:02:15 +08002342 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302343 usecase->type == TRANSCODE_LOOPBACK_RX ||
2344 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002345 return false;
2346 }
2347
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002348 if(usecase->stream.out == NULL) {
2349 ALOGE("%s: stream.out is NULL", __func__);
2350 return false;
2351 }
2352
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302353 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002354 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002355 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2356 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302357 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2358 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2359 (!is_it_true_mode && adev->native_playback_enabled)){
2360 ret = true;
2361 ALOGD("napb: time to toggle native mode");
2362 }
2363 }
2364
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302365 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302366 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2367 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002368 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302369 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302370 ALOGD("Force a2dp device switch to update new encoder config");
2371 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002372 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302373
Florian Pfister1a84f312018-07-19 14:38:18 +02002374 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302375 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2376 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002377 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302378 return ret;
2379}
2380
Aalique Grahame22e49102018-12-18 14:23:57 -08002381static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2382{
2383 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2384}
2385
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302386bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2387{
2388 bool ret=false;
2389 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002390 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2391 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302392 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2393 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002394 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302395 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2396 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2397 ret = true;
2398
2399 return ret;
2400}
2401
2402bool is_a2dp_device(snd_device_t out_snd_device)
2403{
2404 bool ret=false;
2405 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2406 ret = true;
2407
2408 return ret;
2409}
2410
2411bool is_bt_soc_on(struct audio_device *adev)
2412{
2413 struct mixer_ctl *ctl;
2414 char *mixer_ctl_name = "BT SOC status";
2415 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2416 bool bt_soc_status = true;
2417 if (!ctl) {
2418 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2419 __func__, mixer_ctl_name);
2420 /*This is to ensure we dont break targets which dont have the kernel change*/
2421 return true;
2422 }
2423 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2424 ALOGD("BT SOC status: %d",bt_soc_status);
2425 return bt_soc_status;
2426}
2427
Zhou Song331c8e52019-08-26 14:16:12 +08002428static int configure_btsco_sample_rate(snd_device_t snd_device)
2429{
2430 struct mixer_ctl *ctl = NULL;
2431 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2432 char *rate_str = NULL;
2433 bool is_rx_dev = true;
2434
2435 if (is_btsco_device(snd_device, snd_device)) {
2436 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2437 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2438 if (!ctl_sr_tx || !ctl_sr_rx) {
2439 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2440 if (!ctl_sr)
2441 return -ENOSYS;
2442 }
2443
2444 switch (snd_device) {
2445 case SND_DEVICE_OUT_BT_SCO:
2446 rate_str = "KHZ_8";
2447 break;
2448 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2449 case SND_DEVICE_IN_BT_SCO_MIC:
2450 rate_str = "KHZ_8";
2451 is_rx_dev = false;
2452 break;
2453 case SND_DEVICE_OUT_BT_SCO_WB:
2454 rate_str = "KHZ_16";
2455 break;
2456 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2457 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2458 rate_str = "KHZ_16";
2459 is_rx_dev = false;
2460 break;
2461 default:
2462 return 0;
2463 }
2464
2465 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2466 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2467 return -ENOSYS;
2468 }
2469 return 0;
2470}
2471
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302472int out_standby_l(struct audio_stream *stream);
2473
Eric Laurent637e2d42018-11-15 12:24:31 -08002474struct stream_in *adev_get_active_input(const struct audio_device *adev)
2475{
2476 struct listnode *node;
2477 struct stream_in *last_active_in = NULL;
2478
2479 /* Get last added active input.
2480 * TODO: We may use a priority mechanism to pick highest priority active source */
2481 list_for_each(node, &adev->usecase_list)
2482 {
2483 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2484 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2485 last_active_in = usecase->stream.in;
2486 }
2487
2488 return last_active_in;
2489}
2490
2491struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2492{
2493 struct listnode *node;
2494
2495 /* First check active inputs with voice communication source and then
2496 * any input if audio mode is in communication */
2497 list_for_each(node, &adev->usecase_list)
2498 {
2499 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2500 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2501 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2502 return usecase->stream.in;
2503 }
2504 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2505 return adev_get_active_input(adev);
2506
2507 return NULL;
2508}
2509
Carter Hsu2e429db2019-05-14 18:50:52 +08002510/*
2511 * Aligned with policy.h
2512 */
2513static inline int source_priority(int inputSource)
2514{
2515 switch (inputSource) {
2516 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2517 return 9;
2518 case AUDIO_SOURCE_CAMCORDER:
2519 return 8;
2520 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2521 return 7;
2522 case AUDIO_SOURCE_UNPROCESSED:
2523 return 6;
2524 case AUDIO_SOURCE_MIC:
2525 return 5;
2526 case AUDIO_SOURCE_ECHO_REFERENCE:
2527 return 4;
2528 case AUDIO_SOURCE_FM_TUNER:
2529 return 3;
2530 case AUDIO_SOURCE_VOICE_RECOGNITION:
2531 return 2;
2532 case AUDIO_SOURCE_HOTWORD:
2533 return 1;
2534 default:
2535 break;
2536 }
2537 return 0;
2538}
2539
2540static struct stream_in *get_priority_input(struct audio_device *adev)
2541{
2542 struct listnode *node;
2543 struct audio_usecase *usecase;
2544 int last_priority = 0, priority;
2545 struct stream_in *priority_in = NULL;
2546 struct stream_in *in;
2547
2548 list_for_each(node, &adev->usecase_list) {
2549 usecase = node_to_item(node, struct audio_usecase, list);
2550 if (usecase->type == PCM_CAPTURE) {
2551 in = usecase->stream.in;
2552 if (!in)
2553 continue;
2554 priority = source_priority(in->source);
2555
2556 if (priority > last_priority) {
2557 last_priority = priority;
2558 priority_in = in;
2559 }
2560 }
2561 }
2562 return priority_in;
2563}
2564
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002565int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002567 snd_device_t out_snd_device = SND_DEVICE_NONE;
2568 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002569 struct audio_usecase *usecase = NULL;
2570 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002571 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002572 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302573 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002574 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002575 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302577 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002579 usecase = get_usecase_from_list(adev, uc_id);
2580 if (usecase == NULL) {
2581 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2582 return -EINVAL;
2583 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002585 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002586 (usecase->type == VOIP_CALL) ||
2587 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302588 if(usecase->stream.out == NULL) {
2589 ALOGE("%s: stream.out is NULL", __func__);
2590 return -EINVAL;
2591 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002592 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002593 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2594 uc_id);
2595 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2596 uc_id);
2597 } else {
2598 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302599 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002600 in_snd_device = platform_get_input_snd_device(adev->platform,
2601 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302602 &usecase->stream.out->device_list,
2603 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002604 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002605 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302606 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302607 if (usecase->stream.inout == NULL) {
2608 ALOGE("%s: stream.inout is NULL", __func__);
2609 return -EINVAL;
2610 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002611 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302612 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2613 stream_out.format = usecase->stream.inout->out_config.format;
2614 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302615 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002616 assign_devices(&usecase->device_list,
2617 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302618 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2619 if (usecase->stream.inout == NULL) {
2620 ALOGE("%s: stream.inout is NULL", __func__);
2621 return -EINVAL;
2622 }
Jaideep Sharma477917f2020-03-13 18:13:33 +05302623 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, NULL, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002624 assign_devices(&usecase->device_list,
2625 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002626 } else {
2627 /*
2628 * If the voice call is active, use the sound devices of voice call usecase
2629 * so that it would not result any device switch. All the usecases will
2630 * be switched to new device when select_devices() is called for voice call
2631 * usecase. This is to avoid switching devices for voice call when
2632 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002633 * choose voice call device only if the use case device is
2634 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002635 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002636 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002637 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002638 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002639 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2640 is_codec_backend_out_device_type(&usecase->device_list)) ||
2641 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2642 is_codec_backend_in_device_type(&usecase->device_list)) ||
2643 is_single_device_type_equal(&vc_usecase->device_list,
2644 AUDIO_DEVICE_OUT_HEARING_AID) ||
2645 is_single_device_type_equal(&usecase->device_list,
2646 AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002647 in_snd_device = vc_usecase->in_snd_device;
2648 out_snd_device = vc_usecase->out_snd_device;
2649 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002650 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002651 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002652 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002653 if ((voip_usecase != NULL) &&
2654 (usecase->type == PCM_PLAYBACK) &&
2655 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002656 out_snd_device_backend_match = platform_check_backends_match(
2657 voip_usecase->out_snd_device,
2658 platform_get_output_snd_device(
2659 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302660 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002661 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002662 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2663 (is_codec_backend_out_device_type(&usecase->device_list) ||
2664 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002665 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002666 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002667 in_snd_device = voip_usecase->in_snd_device;
2668 out_snd_device = voip_usecase->out_snd_device;
2669 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002670 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002671 hfp_ucid = audio_extn_hfp_get_usecase();
2672 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002673 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002674 in_snd_device = hfp_usecase->in_snd_device;
2675 out_snd_device = hfp_usecase->out_snd_device;
2676 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002677 }
2678 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302679 if (usecase->stream.out == NULL) {
2680 ALOGE("%s: stream.out is NULL", __func__);
2681 return -EINVAL;
2682 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002683 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002684 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002685 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002686 struct stream_out *voip_out = adev->primary_output;
2687 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002688 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002689 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2690 else
2691 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302692 usecase->stream.out,
2693 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002694 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002695
Eric Laurent637e2d42018-11-15 12:24:31 -08002696 if (voip_usecase)
2697 voip_out = voip_usecase->stream.out;
2698
2699 if (usecase->stream.out == voip_out && voip_in != NULL)
2700 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002701 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002702 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302703 if (usecase->stream.in == NULL) {
2704 ALOGE("%s: stream.in is NULL", __func__);
2705 return -EINVAL;
2706 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002707 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002708 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002709 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002710 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002711 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002712 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002713
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002714 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002715 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002716 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2717 USECASE_AUDIO_PLAYBACK_VOIP);
2718
Carter Hsu2e429db2019-05-14 18:50:52 +08002719 usecase->stream.in->enable_ec_port = false;
2720
Eric Laurent637e2d42018-11-15 12:24:31 -08002721 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002722 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002723 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002724 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002725 } else if (adev->primary_output &&
2726 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002727 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002728 } else {
2729 /* forcing speaker o/p device to get matching i/p pair
2730 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002731 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002732 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002733 priority_in = voip_in;
2734 } else {
2735 /* get the input with the highest priority source*/
2736 priority_in = get_priority_input(adev);
2737
2738 if (!priority_in)
2739 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002740 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002741
Eric Laurent637e2d42018-11-15 12:24:31 -08002742 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002743 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302744 &out_devices,
2745 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002746 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002747 }
2748 }
2749
2750 if (out_snd_device == usecase->out_snd_device &&
2751 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302752
2753 if (!force_device_switch(usecase))
2754 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755 }
2756
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002757 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002758 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002759 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002760 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2761 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302762 }
2763
Aalique Grahame22e49102018-12-18 14:23:57 -08002764 if (out_snd_device != SND_DEVICE_NONE &&
2765 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2766 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2767 __func__,
2768 use_case_table[uc_id],
2769 adev->last_logged_snd_device[uc_id][0],
2770 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2771 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2772 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2773 -1,
2774 out_snd_device,
2775 platform_get_snd_device_name(out_snd_device),
2776 platform_get_snd_device_acdb_id(out_snd_device));
2777 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2778 }
2779 if (in_snd_device != SND_DEVICE_NONE &&
2780 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2781 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2782 __func__,
2783 use_case_table[uc_id],
2784 adev->last_logged_snd_device[uc_id][1],
2785 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2786 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2787 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2788 -1,
2789 in_snd_device,
2790 platform_get_snd_device_name(in_snd_device),
2791 platform_get_snd_device_acdb_id(in_snd_device));
2792 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2793 }
2794
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 /*
2797 * Limitation: While in call, to do a device switch we need to disable
2798 * and enable both RX and TX devices though one of them is same as current
2799 * device.
2800 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002801 if ((usecase->type == VOICE_CALL) &&
2802 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2803 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002804 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002805 }
2806
2807 if (((usecase->type == VOICE_CALL) ||
2808 (usecase->type == VOIP_CALL)) &&
2809 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2810 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302811 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002812 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002813 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002814
2815 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302816 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002817 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002818 }
2819
Aalique Grahame22e49102018-12-18 14:23:57 -08002820 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2821 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002822 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302823 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002824 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2825 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2826 else
2827 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302828 }
2829
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002830 /* Disable current sound devices */
2831 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002832 disable_audio_route(adev, usecase);
2833 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834 }
2835
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002836 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002837 disable_audio_route(adev, usecase);
2838 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839 }
2840
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002841 /* Applicable only on the targets that has external modem.
2842 * New device information should be sent to modem before enabling
2843 * the devices to reduce in-call device switch time.
2844 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002845 if ((usecase->type == VOICE_CALL) &&
2846 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2847 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002848 status = platform_switch_voice_call_enable_device_config(adev->platform,
2849 out_snd_device,
2850 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002851 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002852
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002853 /* Enable new sound devices */
2854 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002855 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302856 if (platform_check_codec_asrc_support(adev->platform))
2857 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002858 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859 }
2860
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002861 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302862 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002863 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002864 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002865
Avinash Vaish71a8b972014-07-24 15:36:33 +05302866 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002867 status = platform_switch_voice_call_device_post(adev->platform,
2868 out_snd_device,
2869 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302870 enable_audio_route_for_voice_usecases(adev, usecase);
2871 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002872
sangwoo170731f2013-06-08 15:36:36 +09002873 usecase->in_snd_device = in_snd_device;
2874 usecase->out_snd_device = out_snd_device;
2875
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302876 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2877 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302878 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002879 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002880 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002881 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2882 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2883 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2884 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2885 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2886 /*
2887 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2888 * configured device sample rate, if not update the COPP rate to be equal to the
2889 * device sample rate, else open COPP at stream sample rate
2890 */
2891 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2892 usecase->stream.out->sample_rate,
2893 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302894 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302895 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2896 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302897 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002898 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2899 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2900 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2901 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002902 }
2903 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002904
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002905 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002906
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002907 /* If input stream is already running then effect needs to be
2908 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002909 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002910 check_and_enable_effect(adev);
2911
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002912 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002913 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302914 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002915 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2916
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002917 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302918 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002919 voice_extn_compress_voip_is_started(adev))
2920 voice_set_sidetone(adev, out_snd_device, true);
2921 }
2922
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002923 /* Applicable only on the targets that has external modem.
2924 * Enable device command should be sent to modem only after
2925 * enabling voice call mixer controls
2926 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002927 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002928 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2929 out_snd_device,
2930 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302931
2932 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002933 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302934 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002935 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302936 if (is_bt_soc_on(adev) == false){
2937 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002938 if (in->pcm != NULL)
2939 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302940 }
2941 }
2942 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2943 && usecase->stream.out->started) {
2944 if (is_bt_soc_on(adev) == false) {
2945 ALOGD("BT SCO/A2DP disconnected while in connection");
2946 out_standby_l(&usecase->stream.out->stream.common);
2947 }
2948 }
2949 } else if ((usecase->stream.out != NULL) &&
2950 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302951 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2952 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08002953 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302954 usecase->stream.out->started) {
2955 if (is_bt_soc_on(adev) == false) {
2956 ALOGD("BT SCO/A2dp disconnected while in connection");
2957 out_standby_l(&usecase->stream.out->stream.common);
2958 }
2959 }
2960 }
2961
Yung Ti Su70cb8242018-06-22 17:38:47 +08002962 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002963 struct stream_out *voip_out = voip_usecase->stream.out;
2964 audio_extn_utils_send_app_type_gain(adev,
2965 voip_out->app_type_cfg.app_type,
2966 &voip_out->app_type_cfg.gain[0]);
2967 }
2968
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302969 ALOGD("%s: done",__func__);
2970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 return status;
2972}
2973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974static int stop_input_stream(struct stream_in *in)
2975{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302976 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302978
2979 if (in == NULL) {
2980 ALOGE("%s: stream_in ptr is NULL", __func__);
2981 return -EINVAL;
2982 }
2983
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002985 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986
Eric Laurent994a6932013-07-17 11:51:42 -07002987 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002988 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 uc_info = get_usecase_from_list(adev, in->usecase);
2990 if (uc_info == NULL) {
2991 ALOGE("%s: Could not find the usecase (%d) in the list",
2992 __func__, in->usecase);
2993 return -EINVAL;
2994 }
2995
Carter Hsu2e429db2019-05-14 18:50:52 +08002996 priority_in = get_priority_input(adev);
2997
Derek Chenea197282019-01-07 17:35:01 -08002998 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2999 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003000
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003001 /* Close in-call recording streams */
3002 voice_check_and_stop_incall_rec_usecase(adev, in);
3003
Eric Laurent150dbfe2013-02-27 14:31:02 -08003004 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003005 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003006
3007 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003008 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003010 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303011 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3012
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003013 list_remove(&uc_info->list);
3014 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015
Carter Hsu2e429db2019-05-14 18:50:52 +08003016 if (priority_in == in) {
3017 priority_in = get_priority_input(adev);
3018 if (priority_in)
3019 select_devices(adev, priority_in->usecase);
3020 }
3021
Vatsal Buchac09ae062018-11-14 13:25:08 +05303022 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003023 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 return ret;
3025}
3026
3027int start_input_stream(struct stream_in *in)
3028{
3029 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003030 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303032
3033 if (in == NULL) {
3034 ALOGE("%s: stream_in ptr is NULL", __func__);
3035 return -EINVAL;
3036 }
3037
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003039 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003040 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041
Mingming Yin2664a5b2015-09-03 10:53:11 -07003042 if (get_usecase_from_list(adev, usecase) == NULL)
3043 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303044 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3045 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003046
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303047 if (CARD_STATUS_OFFLINE == in->card_status||
3048 CARD_STATUS_OFFLINE == adev->card_status) {
3049 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303050 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303051 goto error_config;
3052 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303053
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003054 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303055 if (!adev->bt_sco_on) {
3056 ALOGE("%s: SCO profile is not ready, return error", __func__);
3057 ret = -EIO;
3058 goto error_config;
3059 }
3060 }
3061
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003062 /* Check if source matches incall recording usecase criteria */
3063 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3064 if (ret)
3065 goto error_config;
3066 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003067 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3068
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303069 if (audio_extn_cin_attached_usecase(in))
3070 audio_extn_cin_acquire_usecase(in);
3071
Mingming Yin2664a5b2015-09-03 10:53:11 -07003072 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3073 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3074 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003075 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003076 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003077
Eric Laurentb23d5282013-05-14 15:27:20 -07003078 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079 if (in->pcm_device_id < 0) {
3080 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3081 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003082 ret = -EINVAL;
3083 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003087
3088 if (!uc_info) {
3089 ret = -ENOMEM;
3090 goto error_config;
3091 }
3092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003093 uc_info->id = in->usecase;
3094 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003095 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003096 list_init(&uc_info->device_list);
3097 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003098 uc_info->in_snd_device = SND_DEVICE_NONE;
3099 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003101 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003102 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303103 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3104 adev->perf_lock_opts,
3105 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003106 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107
Derek Chenea197282019-01-07 17:35:01 -08003108 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3109 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003110
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303111 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3112
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303113 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303114 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303115 if (ret)
3116 goto error_open;
3117 else
3118 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003119 }
3120
Haynes Mathew George16081042017-05-31 17:16:49 -07003121 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003122 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003123 ALOGE("%s: pcm stream not ready", __func__);
3124 goto error_open;
3125 }
3126 ret = pcm_start(in->pcm);
3127 if (ret < 0) {
3128 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3129 goto error_open;
3130 }
3131 } else {
3132 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3133 unsigned int pcm_open_retry_count = 0;
3134
3135 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
3136 flags |= PCM_MMAP | PCM_NOIRQ;
3137 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3138 } else if (in->realtime) {
3139 flags |= PCM_MMAP | PCM_NOIRQ;
3140 }
3141
Garmond Leunge2433c32017-09-28 21:51:22 -07003142 if (audio_extn_ffv_get_stream() == in) {
3143 ALOGD("%s: ffv stream, update pcm config", __func__);
3144 audio_extn_ffv_update_pcm_config(&config);
3145 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003146 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3147 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3148
3149 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003150 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003151 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003152 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003153 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303154 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303155 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3156 adev->card_status = CARD_STATUS_OFFLINE;
3157 in->card_status = CARD_STATUS_OFFLINE;
3158 ret = -EIO;
3159 goto error_open;
3160 }
3161
Haynes Mathew George16081042017-05-31 17:16:49 -07003162 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3163 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3164 if (in->pcm != NULL) {
3165 pcm_close(in->pcm);
3166 in->pcm = NULL;
3167 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003168 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003169 ret = -EIO;
3170 goto error_open;
3171 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003172 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003173 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3174 continue;
3175 }
3176 break;
3177 }
3178
3179 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003180 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003181 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003182 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003183 if (ret < 0) {
3184 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3185 pcm_close(in->pcm);
3186 in->pcm = NULL;
3187 goto error_open;
3188 }
3189 register_in_stream(in);
3190 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003191 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003192 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003193 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003194 if (ret < 0) {
3195 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003196 pcm_close(in->pcm);
3197 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003198 goto error_open;
3199 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003200 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003201 }
3202
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003203 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003204 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3205 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003206
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003207 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303208 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3209
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303210done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003211 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303212 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003213 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303214 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003215 return ret;
3216
3217error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003218 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303219 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003221
Eric Laurentc8400632013-02-14 19:04:54 -08003222error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303223 /*
3224 * sleep 50ms to allow sufficient time for kernel
3225 * drivers to recover incases like SSR.
3226 */
3227 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003228 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303229 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003230 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231}
3232
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003233void lock_input_stream(struct stream_in *in)
3234{
3235 pthread_mutex_lock(&in->pre_lock);
3236 pthread_mutex_lock(&in->lock);
3237 pthread_mutex_unlock(&in->pre_lock);
3238}
3239
3240void lock_output_stream(struct stream_out *out)
3241{
3242 pthread_mutex_lock(&out->pre_lock);
3243 pthread_mutex_lock(&out->lock);
3244 pthread_mutex_unlock(&out->pre_lock);
3245}
3246
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003247/* must be called with out->lock locked */
3248static int send_offload_cmd_l(struct stream_out* out, int command)
3249{
3250 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3251
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003252 if (!cmd) {
3253 ALOGE("failed to allocate mem for command 0x%x", command);
3254 return -ENOMEM;
3255 }
3256
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003257 ALOGVV("%s %d", __func__, command);
3258
3259 cmd->cmd = command;
3260 list_add_tail(&out->offload_cmd_list, &cmd->node);
3261 pthread_cond_signal(&out->offload_cond);
3262 return 0;
3263}
3264
3265/* must be called iwth out->lock locked */
3266static void stop_compressed_output_l(struct stream_out *out)
3267{
3268 out->offload_state = OFFLOAD_STATE_IDLE;
3269 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003270 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003271 if (out->compr != NULL) {
3272 compress_stop(out->compr);
3273 while (out->offload_thread_blocked) {
3274 pthread_cond_wait(&out->cond, &out->lock);
3275 }
3276 }
3277}
3278
Varun Balaraje49253e2017-07-06 19:48:56 +05303279bool is_interactive_usecase(audio_usecase_t uc_id)
3280{
3281 unsigned int i;
3282 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3283 if (uc_id == interactive_usecases[i])
3284 return true;
3285 }
3286 return false;
3287}
3288
3289static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3290{
3291 audio_usecase_t ret_uc = USECASE_INVALID;
3292 unsigned int intract_uc_index;
3293 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3294
3295 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3296 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3297 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3298 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3299 ret_uc = interactive_usecases[intract_uc_index];
3300 break;
3301 }
3302 }
3303
3304 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3305 return ret_uc;
3306}
3307
3308static void free_interactive_usecase(struct audio_device *adev,
3309 audio_usecase_t uc_id)
3310{
3311 unsigned int interact_uc_index;
3312 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3313
3314 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3315 if (interactive_usecases[interact_uc_index] == uc_id) {
3316 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3317 break;
3318 }
3319 }
3320 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3321}
3322
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003323bool is_offload_usecase(audio_usecase_t uc_id)
3324{
3325 unsigned int i;
3326 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3327 if (uc_id == offload_usecases[i])
3328 return true;
3329 }
3330 return false;
3331}
3332
Dhananjay Kumarac341582017-02-23 23:42:25 +05303333static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003334{
vivek mehta446c3962015-09-14 10:57:35 -07003335 audio_usecase_t ret_uc = USECASE_INVALID;
3336 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003337 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003338 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303339 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003340 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3341 else
3342 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003343
vivek mehta446c3962015-09-14 10:57:35 -07003344 pthread_mutex_lock(&adev->lock);
3345 if (get_usecase_from_list(adev, ret_uc) != NULL)
3346 ret_uc = USECASE_INVALID;
3347 pthread_mutex_unlock(&adev->lock);
3348
3349 return ret_uc;
3350 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003351
3352 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003353 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3354 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3355 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3356 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003357 break;
3358 }
3359 }
vivek mehta446c3962015-09-14 10:57:35 -07003360
3361 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3362 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003363}
3364
3365static void free_offload_usecase(struct audio_device *adev,
3366 audio_usecase_t uc_id)
3367{
vivek mehta446c3962015-09-14 10:57:35 -07003368 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003369 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003370
3371 if (!adev->multi_offload_enable)
3372 return;
3373
3374 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3375 if (offload_usecases[offload_uc_index] == uc_id) {
3376 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003377 break;
3378 }
3379 }
3380 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3381}
3382
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003383static void *offload_thread_loop(void *context)
3384{
3385 struct stream_out *out = (struct stream_out *) context;
3386 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003387 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003388
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003389 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003390 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003391 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3392
3393 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003394 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003395 out->offload_state = OFFLOAD_STATE_IDLE;
3396 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003397 for (;;) {
3398 struct offload_cmd *cmd = NULL;
3399 stream_callback_event_t event;
3400 bool send_callback = false;
3401
3402 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3403 __func__, list_empty(&out->offload_cmd_list),
3404 out->offload_state);
3405 if (list_empty(&out->offload_cmd_list)) {
3406 ALOGV("%s SLEEPING", __func__);
3407 pthread_cond_wait(&out->offload_cond, &out->lock);
3408 ALOGV("%s RUNNING", __func__);
3409 continue;
3410 }
3411
3412 item = list_head(&out->offload_cmd_list);
3413 cmd = node_to_item(item, struct offload_cmd, node);
3414 list_remove(item);
3415
3416 ALOGVV("%s STATE %d CMD %d out->compr %p",
3417 __func__, out->offload_state, cmd->cmd, out->compr);
3418
3419 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3420 free(cmd);
3421 break;
3422 }
3423
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003424 // allow OFFLOAD_CMD_ERROR reporting during standby
3425 // this is needed to handle failures during compress_open
3426 // Note however that on a pause timeout, the stream is closed
3427 // and no offload usecase will be active. Therefore this
3428 // special case is needed for compress_open failures alone
3429 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3430 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003431 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003432 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003433 pthread_cond_signal(&out->cond);
3434 continue;
3435 }
3436 out->offload_thread_blocked = true;
3437 pthread_mutex_unlock(&out->lock);
3438 send_callback = false;
3439 switch(cmd->cmd) {
3440 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003441 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003442 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003443 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003444 send_callback = true;
3445 event = STREAM_CBK_EVENT_WRITE_READY;
3446 break;
3447 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003448 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303449 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003450 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303451 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003452 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303453 if (ret < 0)
3454 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303455 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303456 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003457 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003458 else
3459 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003460 if (-ENETRESET != ret && !(-EINTR == ret &&
3461 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303462 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303463 pthread_mutex_lock(&out->lock);
3464 out->send_new_metadata = 1;
3465 out->send_next_track_params = true;
3466 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303467 event = STREAM_CBK_EVENT_DRAIN_READY;
3468 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3469 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303470 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003471 break;
3472 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003473 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003474 ret = compress_drain(out->compr);
3475 ALOGD("copl(%p):out of compress_drain", out);
3476 // EINTR check avoids drain interruption due to SSR
3477 if (-ENETRESET != ret && !(-EINTR == ret &&
3478 CARD_STATUS_OFFLINE == out->card_status)) {
3479 send_callback = true;
3480 event = STREAM_CBK_EVENT_DRAIN_READY;
3481 } else
3482 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003483 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303484 case OFFLOAD_CMD_ERROR:
3485 ALOGD("copl(%p): sending error callback to AF", out);
3486 send_callback = true;
3487 event = STREAM_CBK_EVENT_ERROR;
3488 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003489 default:
3490 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3491 break;
3492 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003493 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003494 out->offload_thread_blocked = false;
3495 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003496 if (send_callback && out->client_callback) {
3497 ALOGVV("%s: sending client_callback event %d", __func__, event);
3498 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003499 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003500 free(cmd);
3501 }
3502
3503 pthread_cond_signal(&out->cond);
3504 while (!list_empty(&out->offload_cmd_list)) {
3505 item = list_head(&out->offload_cmd_list);
3506 list_remove(item);
3507 free(node_to_item(item, struct offload_cmd, node));
3508 }
3509 pthread_mutex_unlock(&out->lock);
3510
3511 return NULL;
3512}
3513
3514static int create_offload_callback_thread(struct stream_out *out)
3515{
3516 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3517 list_init(&out->offload_cmd_list);
3518 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3519 offload_thread_loop, out);
3520 return 0;
3521}
3522
3523static int destroy_offload_callback_thread(struct stream_out *out)
3524{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003525 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003526 stop_compressed_output_l(out);
3527 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3528
3529 pthread_mutex_unlock(&out->lock);
3530 pthread_join(out->offload_thread, (void **) NULL);
3531 pthread_cond_destroy(&out->offload_cond);
3532
3533 return 0;
3534}
3535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536static int stop_output_stream(struct stream_out *out)
3537{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303538 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539 struct audio_usecase *uc_info;
3540 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003541 bool has_voip_usecase =
3542 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543
Eric Laurent994a6932013-07-17 11:51:42 -07003544 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003545 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546 uc_info = get_usecase_from_list(adev, out->usecase);
3547 if (uc_info == NULL) {
3548 ALOGE("%s: Could not find the usecase (%d) in the list",
3549 __func__, out->usecase);
3550 return -EINVAL;
3551 }
3552
Derek Chenea197282019-01-07 17:35:01 -08003553 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3554 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003555
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003556 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303557 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003558 if (adev->visualizer_stop_output != NULL)
3559 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003560
3561 audio_extn_dts_remove_state_notifier_node(out->usecase);
3562
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003563 if (adev->offload_effects_stop_output != NULL)
3564 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003565 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3566 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3567 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003568 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003569
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003570 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3571 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003572 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003573 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003574
Eric Laurent150dbfe2013-02-27 14:31:02 -08003575 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003576 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003577
3578 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003579 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580
Aalique Grahame22e49102018-12-18 14:23:57 -08003581 audio_extn_extspk_update(adev->extspk);
3582
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003583 if (is_offload_usecase(out->usecase)) {
3584 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3585 adev->dsp_bit_width_enforce_mode,
3586 false);
3587 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003588 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003589 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3590 false);
3591
3592 if (ret != 0)
3593 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3594 /* default service interval was successfully updated,
3595 reopen USB backend with new service interval */
3596 ret = 0;
3597 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003598
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003599 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303600 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003601 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303602 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003603 ALOGV("Disable passthrough , reset mixer to pcm");
3604 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003605#ifdef AUDIO_GKI_ENABLED
3606 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3607 out->compr_config.codec->reserved[0] = 0;
3608#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003609 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003610#endif
Mingming Yin21854652016-04-13 11:54:02 -07003611 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003612 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3613 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003614
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303615 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003616 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303617 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303618
Manish Dewangan21a850a2017-08-14 12:03:55 +05303619 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003620 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3621 if (ret < 0)
3622 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3623 }
3624
juyuchen2d415992018-11-16 14:15:16 +08003625 /* 1) media + voip output routing to handset must route media back to
3626 speaker when voip stops.
3627 2) trigger voip input to reroute when voip output changes to
3628 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003629 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003630 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003631 struct listnode *node;
3632 struct audio_usecase *usecase;
3633 list_for_each(node, &adev->usecase_list) {
3634 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003635 if ((usecase->type == PCM_CAPTURE &&
3636 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3637 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003638 continue;
3639
3640 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3641 __func__, usecase->id, use_case_table[usecase->id],
3642 out->usecase, use_case_table[out->usecase]);
3643 select_devices(adev, usecase->id);
3644 }
3645 }
3646
Garmond Leung5fd0b552018-04-17 11:56:12 -07003647 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003648 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649 return ret;
3650}
3651
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003652struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3653 unsigned int flags, unsigned int pcm_open_retry_count,
3654 struct pcm_config *config)
3655{
3656 struct pcm* pcm = NULL;
3657
3658 while (1) {
3659 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3660 if (pcm == NULL || !pcm_is_ready(pcm)) {
3661 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3662 if (pcm != NULL) {
3663 pcm_close(pcm);
3664 pcm = NULL;
3665 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003666 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003667 return NULL;
3668
Weiyin Jiang72197252019-10-09 11:49:32 +08003669 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003670 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3671 continue;
3672 }
3673 break;
3674 }
3675
3676 if (pcm_is_ready(pcm)) {
3677 int ret = pcm_prepare(pcm);
3678 if (ret < 0) {
3679 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3680 pcm_close(pcm);
3681 pcm = NULL;
3682 }
3683 }
3684
3685 return pcm;
3686}
3687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688int start_output_stream(struct stream_out *out)
3689{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691 struct audio_usecase *uc_info;
3692 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003693 char mixer_ctl_name[128];
3694 struct mixer_ctl *ctl = NULL;
3695 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303696 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003697 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698
Haynes Mathew George380745d2017-10-04 15:27:45 -07003699 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003700 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3701 ret = -EINVAL;
3702 goto error_config;
3703 }
3704
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003705 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303706 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003707 get_device_types(&out->device_list), is_haptic_usecase);
3708
3709 bool is_speaker_active = compare_device_type(&out->device_list,
3710 AUDIO_DEVICE_OUT_SPEAKER);
3711 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3712 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303713
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303714 if (CARD_STATUS_OFFLINE == out->card_status ||
3715 CARD_STATUS_OFFLINE == adev->card_status) {
3716 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303717 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003718 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303719 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303720
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003721 //Update incall music usecase to reflect correct voice session
3722 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3723 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3724 if (ret != 0) {
3725 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3726 __func__, ret);
3727 goto error_config;
3728 }
3729 }
3730
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003731 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003732 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003733 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303734 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303735 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303736 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3737 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3738 ret = -EAGAIN;
3739 goto error_config;
3740 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303741 }
3742 }
3743 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003744 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303745 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003746 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303747 //combo usecase just by pass a2dp
3748 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003749 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303750 } else {
3751 ALOGE("%s: SCO profile is not ready, return error", __func__);
3752 ret = -EAGAIN;
3753 goto error_config;
3754 }
3755 }
3756 }
3757
Eric Laurentb23d5282013-05-14 15:27:20 -07003758 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 if (out->pcm_device_id < 0) {
3760 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3761 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003762 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003763 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 }
3765
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003766 if (is_haptic_usecase) {
3767 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3768 if (adev->haptic_pcm_device_id < 0) {
3769 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3770 __func__, adev->haptic_pcm_device_id, out->usecase);
3771 ret = -EINVAL;
3772 goto error_config;
3773 }
3774 }
3775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003777
3778 if (!uc_info) {
3779 ret = -ENOMEM;
3780 goto error_config;
3781 }
3782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783 uc_info->id = out->usecase;
3784 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003785 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003786 list_init(&uc_info->device_list);
3787 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003788 uc_info->in_snd_device = SND_DEVICE_NONE;
3789 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003790
3791 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003792 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003793 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3794 /* USB backend is not reopened immediately.
3795 This is eventually done as part of select_devices */
3796 }
3797
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003798 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003799
Wei Wangf7ca6c92017-11-21 14:51:20 -08003800 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303801 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3802 adev->perf_lock_opts,
3803 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303804
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003805 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303806 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303807 if (audio_extn_passthru_is_enabled() &&
3808 audio_extn_passthru_is_passthrough_stream(out)) {
3809 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303810 }
3811 }
3812
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003813 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003814 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303815 if (!a2dp_combo) {
3816 check_a2dp_restore_l(adev, out, false);
3817 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003818 struct listnode dev;
3819 list_init(&dev);
3820 assign_devices(&dev, &out->device_list);
3821 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3822 reassign_device_list(&out->device_list,
3823 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003824 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003825 reassign_device_list(&out->device_list,
3826 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303827 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003828 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303829 }
3830 } else {
3831 select_devices(adev, out->usecase);
3832 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003833
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003834 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3835 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003836 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003837 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003838
Derek Chenea197282019-01-07 17:35:01 -08003839 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3840 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003841
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003842 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3843 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003844
3845 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003846 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003847 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3848 ALOGE("%s: pcm stream not ready", __func__);
3849 goto error_open;
3850 }
3851 ret = pcm_start(out->pcm);
3852 if (ret < 0) {
3853 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3854 goto error_open;
3855 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003856 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003857 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003858 unsigned int flags = PCM_OUT;
3859 unsigned int pcm_open_retry_count = 0;
3860 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3861 flags |= PCM_MMAP | PCM_NOIRQ;
3862 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003863 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003864 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003865 } else
3866 flags |= PCM_MONOTONIC;
3867
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003868 if ((adev->vr_audio_mode_enabled) &&
3869 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3870 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3871 "PCM_Dev %d Topology", out->pcm_device_id);
3872 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3873 if (!ctl) {
3874 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3875 __func__, mixer_ctl_name);
3876 } else {
3877 //if success use ULLPP
3878 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3879 __func__, mixer_ctl_name, out->pcm_device_id);
3880 //There is a still a possibility that some sessions
3881 // that request for FAST|RAW when 3D audio is active
3882 //can go through ULLPP. Ideally we expects apps to
3883 //listen to audio focus and stop concurrent playback
3884 //Also, we will look for mode flag (voice_in_communication)
3885 //before enabling the realtime flag.
3886 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3887 }
3888 }
3889
Surendar Karka91fa3682018-07-02 18:12:12 +05303890 if (out->realtime)
3891 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3892 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3893
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003894 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3895 flags, pcm_open_retry_count,
3896 &(out->config));
3897 if (out->pcm == NULL) {
3898 ret = -EIO;
3899 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003900 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003901
3902 if (is_haptic_usecase) {
3903 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3904 adev->haptic_pcm_device_id,
3905 flags, pcm_open_retry_count,
3906 &(adev->haptics_config));
3907 // failure to open haptics pcm shouldnt stop audio,
3908 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003909
3910 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3911 ALOGD("%s: enable haptic audio synchronization", __func__);
3912 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3913 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003914 }
3915
Surendar Karka91fa3682018-07-02 18:12:12 +05303916 if (!out->realtime)
3917 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303918 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003919
Zhou Song2b8f28f2017-09-11 10:51:38 +08003920 // apply volume for voip playback after path is set up
3921 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3922 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303923 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3924 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303925 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3926 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003927 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3928 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303929 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003930 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003931 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303932 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003933 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3934 adev->dsp_bit_width_enforce_mode,
3935 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003937 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003938 out->compr = compress_open(adev->snd_card,
3939 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003940 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003941 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303942 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303943 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3944 adev->card_status = CARD_STATUS_OFFLINE;
3945 out->card_status = CARD_STATUS_OFFLINE;
3946 ret = -EIO;
3947 goto error_open;
3948 }
3949
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003950 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003951 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003952 compress_close(out->compr);
3953 out->compr = NULL;
3954 ret = -EIO;
3955 goto error_open;
3956 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303957 /* compress_open sends params of the track, so reset the flag here */
3958 out->is_compr_metadata_avail = false;
3959
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003960 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003961 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003962
Fred Oh3f43e742015-03-04 18:42:34 -08003963 /* Since small bufs uses blocking writes, a write will be blocked
3964 for the default max poll time (20s) in the event of an SSR.
3965 Reduce the poll time to observe and deal with SSR faster.
3966 */
Ashish Jain5106d362016-05-11 19:23:33 +05303967 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003968 compress_set_max_poll_wait(out->compr, 1000);
3969 }
3970
Manish Dewangan69426c82017-01-30 17:35:36 +05303971 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303972 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303973
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003974 audio_extn_dts_create_state_notifier_node(out->usecase);
3975 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3976 popcount(out->channel_mask),
3977 out->playback_started);
3978
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003979#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303980 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003981 audio_extn_dolby_send_ddp_endp_params(adev);
3982#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303983 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3984 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003985 if (adev->visualizer_start_output != NULL)
3986 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3987 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303988 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003989 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003990 }
Derek Chenf13dd492018-11-13 14:53:51 -08003991
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003992 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08003993 /* Update cached volume from media to offload/direct stream */
3994 struct listnode *node = NULL;
3995 list_for_each(node, &adev->active_outputs_list) {
3996 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3997 streams_output_ctxt_t,
3998 list);
3999 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
4000 out->volume_l = out_ctxt->output->volume_l;
4001 out->volume_r = out_ctxt->output->volume_r;
4002 }
4003 }
4004 out_set_compr_volume(&out->stream,
4005 out->volume_l, out->volume_r);
4006 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004007 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004008
4009 if (ret == 0) {
4010 register_out_stream(out);
4011 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004012 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4013 ALOGE("%s: pcm stream not ready", __func__);
4014 goto error_open;
4015 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004016 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004017 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004018 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004019 if (ret < 0)
4020 goto error_open;
4021 }
4022 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004023 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304024 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004025 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004026
vivek mehtad15d2bf2019-05-17 13:35:10 -07004027 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4028 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4029 audio_low_latency_hint_start();
4030 }
4031
Manish Dewangan21a850a2017-08-14 12:03:55 +05304032 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004033 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004034 if (ret < 0)
4035 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4036 }
4037
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004038 // consider a scenario where on pause lower layers are tear down.
4039 // so on resume, swap mixer control need to be sent only when
4040 // backend is active, hence rather than sending from enable device
4041 // sending it from start of streamtream
4042
4043 platform_set_swap_channels(adev, true);
4044
Haynes Mathew George380745d2017-10-04 15:27:45 -07004045 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304046 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004047 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004048error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004049 if (adev->haptic_pcm) {
4050 pcm_close(adev->haptic_pcm);
4051 adev->haptic_pcm = NULL;
4052 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004053 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304054 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004056error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304057 /*
4058 * sleep 50ms to allow sufficient time for kernel
4059 * drivers to recover incases like SSR.
4060 */
4061 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004062error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004063 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304064 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004065 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004066}
4067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068static int check_input_parameters(uint32_t sample_rate,
4069 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004070 int channel_count,
4071 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004072{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004073 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004074
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304075 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4076 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4077 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004078 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004079 !audio_extn_compr_cap_format_supported(format) &&
4080 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004081 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004082
Aalique Grahame22e49102018-12-18 14:23:57 -08004083 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4084 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4085 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4086 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4087 return -EINVAL;
4088 }
4089
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004090 switch (channel_count) {
4091 case 1:
4092 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304093 case 3:
4094 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004095 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004096 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304097 case 10:
4098 case 12:
4099 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004100 break;
4101 default:
4102 ret = -EINVAL;
4103 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004104
4105 switch (sample_rate) {
4106 case 8000:
4107 case 11025:
4108 case 12000:
4109 case 16000:
4110 case 22050:
4111 case 24000:
4112 case 32000:
4113 case 44100:
4114 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004115 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304116 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004117 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304118 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004119 break;
4120 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004121 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004122 }
4123
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004124 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125}
4126
Naresh Tanniru04f71882018-06-26 17:46:22 +05304127
4128/** Add a value in a list if not already present.
4129 * @return true if value was successfully inserted or already present,
4130 * false if the list is full and does not contain the value.
4131 */
4132static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4133 for (size_t i = 0; i < list_length; i++) {
4134 if (list[i] == value) return true; // value is already present
4135 if (list[i] == 0) { // no values in this slot
4136 list[i] = value;
4137 return true; // value inserted
4138 }
4139 }
4140 return false; // could not insert value
4141}
4142
4143/** Add channel_mask in supported_channel_masks if not already present.
4144 * @return true if channel_mask was successfully inserted or already present,
4145 * false if supported_channel_masks is full and does not contain channel_mask.
4146 */
4147static void register_channel_mask(audio_channel_mask_t channel_mask,
4148 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4149 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4150 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4151}
4152
4153/** Add format in supported_formats if not already present.
4154 * @return true if format was successfully inserted or already present,
4155 * false if supported_formats is full and does not contain format.
4156 */
4157static void register_format(audio_format_t format,
4158 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4159 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4160 "%s: stream can not declare supporting its format %x", __func__, format);
4161}
4162/** Add sample_rate in supported_sample_rates if not already present.
4163 * @return true if sample_rate was successfully inserted or already present,
4164 * false if supported_sample_rates is full and does not contain sample_rate.
4165 */
4166static void register_sample_rate(uint32_t sample_rate,
4167 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4168 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4169 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4170}
4171
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004172static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4173{
4174 uint32_t high = num1, low = num2, temp = 0;
4175
4176 if (!num1 || !num2)
4177 return 0;
4178
4179 if (num1 < num2) {
4180 high = num2;
4181 low = num1;
4182 }
4183
4184 while (low != 0) {
4185 temp = low;
4186 low = high % low;
4187 high = temp;
4188 }
4189 return (num1 * num2)/high;
4190}
4191
4192static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4193{
4194 uint32_t remainder = 0;
4195
4196 if (!multiplier)
4197 return num;
4198
4199 remainder = num % multiplier;
4200 if (remainder)
4201 num += (multiplier - remainder);
4202
4203 return num;
4204}
4205
Aalique Grahame22e49102018-12-18 14:23:57 -08004206static size_t get_stream_buffer_size(size_t duration_ms,
4207 uint32_t sample_rate,
4208 audio_format_t format,
4209 int channel_count,
4210 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004211{
4212 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004213 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214
Aalique Grahame22e49102018-12-18 14:23:57 -08004215 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004216 if (is_low_latency)
4217 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304218
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004219 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004220 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004221
Ralf Herzbd08d632018-09-28 15:50:49 +02004222 /* make sure the size is multiple of 32 bytes and additionally multiple of
4223 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004224 * At 48 kHz mono 16-bit PCM:
4225 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4226 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004227 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004228 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004229 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004230
4231 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004232}
4233
Aalique Grahame22e49102018-12-18 14:23:57 -08004234static size_t get_input_buffer_size(uint32_t sample_rate,
4235 audio_format_t format,
4236 int channel_count,
4237 bool is_low_latency)
4238{
4239 /* Don't know if USB HIFI in this context so use true to be conservative */
4240 if (check_input_parameters(sample_rate, format, channel_count,
4241 true /*is_usb_hifi */) != 0)
4242 return 0;
4243
4244 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4245 sample_rate,
4246 format,
4247 channel_count,
4248 is_low_latency);
4249}
4250
Derek Chenf6318be2017-06-12 17:16:24 -04004251size_t get_output_period_size(uint32_t sample_rate,
4252 audio_format_t format,
4253 int channel_count,
4254 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304255{
4256 size_t size = 0;
4257 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4258
4259 if ((duration == 0) || (sample_rate == 0) ||
4260 (bytes_per_sample == 0) || (channel_count == 0)) {
4261 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4262 bytes_per_sample, channel_count);
4263 return -EINVAL;
4264 }
4265
4266 size = (sample_rate *
4267 duration *
4268 bytes_per_sample *
4269 channel_count) / 1000;
4270 /*
4271 * To have same PCM samples for all channels, the buffer size requires to
4272 * be multiple of (number of channels * bytes per sample)
4273 * For writes to succeed, the buffer must be written at address which is multiple of 32
4274 */
4275 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4276
4277 return (size/(channel_count * bytes_per_sample));
4278}
4279
Zhou Song48453a02018-01-10 17:50:59 +08004280static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304281{
4282 uint64_t actual_frames_rendered = 0;
4283 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4284
4285 /* This adjustment accounts for buffering after app processor.
4286 * It is based on estimated DSP latency per use case, rather than exact.
4287 */
4288 int64_t platform_latency = platform_render_latency(out->usecase) *
4289 out->sample_rate / 1000000LL;
4290
Zhou Song48453a02018-01-10 17:50:59 +08004291 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304292 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4293 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4294 * hence only estimate.
4295 */
George Gao62ebc722019-07-29 16:29:44 -07004296 uint64_t signed_frames = 0;
4297 if (out->written >= kernel_buffer_size)
4298 signed_frames = out->written - kernel_buffer_size;
Ashish Jain5106d362016-05-11 19:23:33 +05304299
George Gao62ebc722019-07-29 16:29:44 -07004300 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask));
4301 if (signed_frames >= platform_latency)
4302 signed_frames = signed_frames - platform_latency;
Ashish Jain5106d362016-05-11 19:23:33 +05304303
Zhou Song48453a02018-01-10 17:50:59 +08004304 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304305 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004306 if (timestamp != NULL )
4307 *timestamp = out->writeAt;
4308 } else if (timestamp != NULL) {
4309 clock_gettime(CLOCK_MONOTONIC, timestamp);
4310 }
4311 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304312
4313 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
George Gao62ebc722019-07-29 16:29:44 -07004314 "bytes/sample %zu channel count %d", __func__, signed_frames,
Ashish Jain5106d362016-05-11 19:23:33 +05304315 (long long int)out->written, (int)kernel_buffer_size,
4316 audio_bytes_per_sample(out->compr_config.codec->format),
4317 popcount(out->channel_mask));
4318
4319 return actual_frames_rendered;
4320}
4321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4323{
4324 struct stream_out *out = (struct stream_out *)stream;
4325
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004326 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327}
4328
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004329static int out_set_sample_rate(struct audio_stream *stream __unused,
4330 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004331{
4332 return -ENOSYS;
4333}
4334
4335static size_t out_get_buffer_size(const struct audio_stream *stream)
4336{
4337 struct stream_out *out = (struct stream_out *)stream;
4338
Varun Balaraje49253e2017-07-06 19:48:56 +05304339 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304340 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304341 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304342 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4343 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4344 else
4345 return out->compr_config.fragment_size;
4346 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004347 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304348 else if (is_offload_usecase(out->usecase) &&
4349 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304350 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004351
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004352 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004353 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354}
4355
4356static uint32_t out_get_channels(const struct audio_stream *stream)
4357{
4358 struct stream_out *out = (struct stream_out *)stream;
4359
4360 return out->channel_mask;
4361}
4362
4363static audio_format_t out_get_format(const struct audio_stream *stream)
4364{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004365 struct stream_out *out = (struct stream_out *)stream;
4366
4367 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004368}
4369
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004370static int out_set_format(struct audio_stream *stream __unused,
4371 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004372{
4373 return -ENOSYS;
4374}
4375
4376static int out_standby(struct audio_stream *stream)
4377{
4378 struct stream_out *out = (struct stream_out *)stream;
4379 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004380 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004381
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304382 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4383 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004384
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004385 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004386 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004387 if (adev->adm_deregister_stream)
4388 adev->adm_deregister_stream(adev->adm_data, out->handle);
4389
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004390 if (is_offload_usecase(out->usecase))
4391 stop_compressed_output_l(out);
4392
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004393 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004394 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004395 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4396 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304397 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004398 pthread_mutex_unlock(&adev->lock);
4399 pthread_mutex_unlock(&out->lock);
4400 ALOGD("VOIP output entered standby");
4401 return 0;
4402 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004403 if (out->pcm) {
4404 pcm_close(out->pcm);
4405 out->pcm = NULL;
4406 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004407 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4408 do_stop = out->playback_started;
4409 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004410
4411 if (out->mmap_shared_memory_fd >= 0) {
4412 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4413 __func__, out->mmap_shared_memory_fd);
4414 close(out->mmap_shared_memory_fd);
4415 out->mmap_shared_memory_fd = -1;
4416 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004417 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004418 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004419 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304420 out->send_next_track_params = false;
4421 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004422 out->gapless_mdata.encoder_delay = 0;
4423 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004424 if (out->compr != NULL) {
4425 compress_close(out->compr);
4426 out->compr = NULL;
4427 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004428 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004429 if (do_stop) {
4430 stop_output_stream(out);
4431 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304432 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004433 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004434 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004435 }
4436 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304437 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004438 return 0;
4439}
4440
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304441static int out_on_error(struct audio_stream *stream)
4442{
4443 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004444 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304445
4446 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004447 // always send CMD_ERROR for offload streams, this
4448 // is needed e.g. when SSR happens within compress_open
4449 // since the stream is active, offload_callback_thread is also active.
4450 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4451 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004452 }
4453 pthread_mutex_unlock(&out->lock);
4454
4455 status = out_standby(&out->stream.common);
4456
4457 lock_output_stream(out);
4458 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004459 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304460 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304461
4462 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4463 ALOGD("Setting previous card status if offline");
4464 out->prev_card_status_offline = true;
4465 }
4466
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304467 pthread_mutex_unlock(&out->lock);
4468
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004469 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304470}
4471
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304472/*
4473 *standby implementation without locks, assumes that the callee already
4474 *has taken adev and out lock.
4475 */
4476int out_standby_l(struct audio_stream *stream)
4477{
4478 struct stream_out *out = (struct stream_out *)stream;
4479 struct audio_device *adev = out->dev;
4480
4481 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4482 stream, out->usecase, use_case_table[out->usecase]);
4483
4484 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004485 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304486 if (adev->adm_deregister_stream)
4487 adev->adm_deregister_stream(adev->adm_data, out->handle);
4488
4489 if (is_offload_usecase(out->usecase))
4490 stop_compressed_output_l(out);
4491
4492 out->standby = true;
4493 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4494 voice_extn_compress_voip_close_output_stream(stream);
4495 out->started = 0;
4496 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004497 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304498 return 0;
4499 } else if (!is_offload_usecase(out->usecase)) {
4500 if (out->pcm) {
4501 pcm_close(out->pcm);
4502 out->pcm = NULL;
4503 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004504 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4505 if (adev->haptic_pcm) {
4506 pcm_close(adev->haptic_pcm);
4507 adev->haptic_pcm = NULL;
4508 }
4509
4510 if (adev->haptic_buffer != NULL) {
4511 free(adev->haptic_buffer);
4512 adev->haptic_buffer = NULL;
4513 adev->haptic_buffer_size = 0;
4514 }
4515 adev->haptic_pcm_device_id = 0;
4516 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304517 } else {
4518 ALOGD("copl(%p):standby", out);
4519 out->send_next_track_params = false;
4520 out->is_compr_metadata_avail = false;
4521 out->gapless_mdata.encoder_delay = 0;
4522 out->gapless_mdata.encoder_padding = 0;
4523 if (out->compr != NULL) {
4524 compress_close(out->compr);
4525 out->compr = NULL;
4526 }
4527 }
4528 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004529 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304530 }
4531 ALOGD("%s: exit", __func__);
4532 return 0;
4533}
4534
Aalique Grahame22e49102018-12-18 14:23:57 -08004535static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004536{
Aalique Grahame22e49102018-12-18 14:23:57 -08004537 struct stream_out *out = (struct stream_out *)stream;
4538
4539 // We try to get the lock for consistency,
4540 // but it isn't necessary for these variables.
4541 // If we're not in standby, we may be blocked on a write.
4542 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4543 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4544 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4545
4546 if (locked) {
4547 pthread_mutex_unlock(&out->lock);
4548 }
4549
4550 // dump error info
4551 (void)error_log_dump(
4552 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004554 return 0;
4555}
4556
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004557static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4558{
4559 int ret = 0;
4560 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004561
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004562 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004563 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004564 return -EINVAL;
4565 }
4566
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304567 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004568
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004569 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4570 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304571 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004572 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004573 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4574 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304575 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004576 }
4577
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004578 ALOGV("%s new encoder delay %u and padding %u", __func__,
4579 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4580
4581 return 0;
4582}
4583
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004584static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4585{
4586 return out == adev->primary_output || out == adev->voice_tx_output;
4587}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004588
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304589// note: this call is safe only if the stream_cb is
4590// removed first in close_output_stream (as is done now).
4591static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4592{
4593 if (!stream || !parms)
4594 return;
4595
4596 struct stream_out *out = (struct stream_out *)stream;
4597 struct audio_device *adev = out->dev;
4598
4599 card_status_t status;
4600 int card;
4601 if (parse_snd_card_status(parms, &card, &status) < 0)
4602 return;
4603
4604 pthread_mutex_lock(&adev->lock);
4605 bool valid_cb = (card == adev->snd_card);
4606 pthread_mutex_unlock(&adev->lock);
4607
4608 if (!valid_cb)
4609 return;
4610
4611 lock_output_stream(out);
4612 if (out->card_status != status)
4613 out->card_status = status;
4614 pthread_mutex_unlock(&out->lock);
4615
4616 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4617 use_case_table[out->usecase],
4618 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4619
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304620 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304621 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304622 if (voice_is_call_state_active(adev) &&
4623 out == adev->primary_output) {
4624 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4625 pthread_mutex_lock(&adev->lock);
4626 voice_stop_call(adev);
4627 adev->mode = AUDIO_MODE_NORMAL;
4628 pthread_mutex_unlock(&adev->lock);
4629 }
4630 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304631 return;
4632}
4633
Kevin Rocardfce19002017-08-07 19:21:36 -07004634static int get_alive_usb_card(struct str_parms* parms) {
4635 int card;
4636 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4637 !audio_extn_usb_alive(card)) {
4638 return card;
4639 }
4640 return -ENODEV;
4641}
4642
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004643int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004644 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004645{
4646 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004647 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004648 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004649 bool bypass_a2dp = false;
4650 bool reconfig = false;
4651 unsigned long service_interval = 0;
4652
4653 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004654 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4655
4656 list_init(&new_devices);
4657 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004658
4659 lock_output_stream(out);
4660 pthread_mutex_lock(&adev->lock);
4661
4662 /*
4663 * When HDMI cable is unplugged the music playback is paused and
4664 * the policy manager sends routing=0. But the audioflinger continues
4665 * to write data until standby time (3sec). As the HDMI core is
4666 * turned off, the write gets blocked.
4667 * Avoid this by routing audio to speaker until standby.
4668 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004669 if (is_single_device_type_equal(&out->device_list,
4670 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004671 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004672 !audio_extn_passthru_is_passthrough_stream(out) &&
4673 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004674 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004675 }
4676 /*
4677 * When A2DP is disconnected the
4678 * music playback is paused and the policy manager sends routing=0
4679 * But the audioflinger continues to write data until standby time
4680 * (3sec). As BT is turned off, the write gets blocked.
4681 * Avoid this by routing audio to speaker until standby.
4682 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004683 if (is_a2dp_out_device_type(&out->device_list) &&
4684 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004685 !audio_extn_a2dp_source_is_ready() &&
4686 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004687 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004688 }
4689 /*
4690 * When USB headset is disconnected the music platback paused
4691 * and the policy manager send routing=0. But if the USB is connected
4692 * back before the standby time, AFE is not closed and opened
4693 * when USB is connected back. So routing to speker will guarantee
4694 * AFE reconfiguration and AFE will be opend once USB is connected again
4695 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004696 if (is_usb_out_device_type(&out->device_list) &&
4697 list_empty(&new_devices) &&
4698 !audio_extn_usb_connected(NULL)) {
4699 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4700 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004701 /* To avoid a2dp to sco overlapping / BT device improper state
4702 * check with BT lib about a2dp streaming support before routing
4703 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004704 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004705 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004706 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4707 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004708 //combo usecase just by pass a2dp
4709 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4710 bypass_a2dp = true;
4711 } else {
4712 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4713 /* update device to a2dp and don't route as BT returned error
4714 * However it is still possible a2dp routing called because
4715 * of current active device disconnection (like wired headset)
4716 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004717 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004718 pthread_mutex_unlock(&adev->lock);
4719 pthread_mutex_unlock(&out->lock);
4720 goto error;
4721 }
4722 }
4723 }
4724
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004725 // Workaround: If routing to an non existing usb device, fail gracefully
4726 // The routing request will otherwise block during 10 second
4727 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004728 if (is_usb_out_device_type(&new_devices)) {
4729 struct str_parms *parms =
4730 str_parms_create_str(get_usb_device_address(&new_devices));
4731 if (!parms)
4732 goto error;
4733 if ((card = get_alive_usb_card(parms)) >= 0) {
4734 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4735 pthread_mutex_unlock(&adev->lock);
4736 pthread_mutex_unlock(&out->lock);
4737 str_parms_destroy(parms);
4738 ret = -ENOSYS;
4739 goto error;
4740 }
4741 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004742 }
4743
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004744 // Workaround: If routing to an non existing hdmi device, fail gracefully
4745 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4746 (platform_get_edid_info_v2(adev->platform,
4747 out->extconn.cs.controller,
4748 out->extconn.cs.stream) != 0)) {
4749 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4750 pthread_mutex_unlock(&adev->lock);
4751 pthread_mutex_unlock(&out->lock);
4752 ret = -ENOSYS;
4753 goto error;
4754 }
4755
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004756 /*
4757 * select_devices() call below switches all the usecases on the same
4758 * backend to the new device. Refer to check_usecases_codec_backend() in
4759 * the select_devices(). But how do we undo this?
4760 *
4761 * For example, music playback is active on headset (deep-buffer usecase)
4762 * and if we go to ringtones and select a ringtone, low-latency usecase
4763 * will be started on headset+speaker. As we can't enable headset+speaker
4764 * and headset devices at the same time, select_devices() switches the music
4765 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4766 * So when the ringtone playback is completed, how do we undo the same?
4767 *
4768 * We are relying on the out_set_parameters() call on deep-buffer output,
4769 * once the ringtone playback is ended.
4770 * NOTE: We should not check if the current devices are same as new devices.
4771 * Because select_devices() must be called to switch back the music
4772 * playback to headset.
4773 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004774 if (!list_empty(&new_devices)) {
4775 bool same_dev = compare_devices(&out->device_list, &new_devices);
4776 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004777
4778 if (output_drives_call(adev, out)) {
4779 if (!voice_is_call_state_active(adev)) {
4780 if (adev->mode == AUDIO_MODE_IN_CALL) {
4781 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004782 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004783 service_interval =
4784 audio_extn_usb_find_service_interval(true, true /*playback*/);
4785 audio_extn_usb_set_service_interval(true /*playback*/,
4786 service_interval,
4787 &reconfig);
4788 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4789 }
4790 ret = voice_start_call(adev);
4791 }
4792 } else {
4793 adev->current_call_output = out;
4794 voice_update_devices_for_all_voice_usecases(adev);
4795 }
4796 }
4797
4798 if (!out->standby) {
4799 if (!same_dev) {
4800 ALOGV("update routing change");
4801 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4802 adev->perf_lock_opts,
4803 adev->perf_lock_opts_size);
4804 if (adev->adm_on_routing_change)
4805 adev->adm_on_routing_change(adev->adm_data,
4806 out->handle);
4807 }
4808 if (!bypass_a2dp) {
4809 select_devices(adev, out->usecase);
4810 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004811 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4812 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004813 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004814 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004815 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004816 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004817 }
4818
4819 if (!same_dev) {
4820 // on device switch force swap, lower functions will make sure
4821 // to check if swap is allowed or not.
4822 platform_set_swap_channels(adev, true);
4823 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4824 }
4825 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4826 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004827 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004828 pthread_mutex_lock(&out->compr_mute_lock);
4829 out->a2dp_compress_mute = false;
4830 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4831 pthread_mutex_unlock(&out->compr_mute_lock);
4832 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4833 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4834 }
4835 }
4836 }
4837
4838 pthread_mutex_unlock(&adev->lock);
4839 pthread_mutex_unlock(&out->lock);
4840
4841 /*handles device and call state changes*/
4842 audio_extn_extspk_update(adev->extspk);
4843
4844error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004845 ALOGV("%s: exit: code(%d)", __func__, ret);
4846 return ret;
4847}
4848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004849static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4850{
4851 struct stream_out *out = (struct stream_out *)stream;
4852 struct audio_device *adev = out->dev;
4853 struct str_parms *parms;
4854 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004855 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004856 int ext_controller = -1;
4857 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004858
sangwoobc677242013-08-08 16:53:43 +09004859 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004860 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004861 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304862 if (!parms)
4863 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004864
4865 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4866 &ext_stream);
Vignesh Kulothungan1b3957e2019-12-02 16:16:51 -08004867 if (err == 0) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004868 out->extconn.cs.controller = ext_controller;
4869 out->extconn.cs.stream = ext_stream;
4870 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4871 use_case_table[out->usecase], out->extconn.cs.controller,
4872 out->extconn.cs.stream);
4873 }
4874
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004875 if (out == adev->primary_output) {
4876 pthread_mutex_lock(&adev->lock);
4877 audio_extn_set_parameters(adev, parms);
4878 pthread_mutex_unlock(&adev->lock);
4879 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004880 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004881 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004882 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004883
4884 audio_extn_dts_create_state_notifier_node(out->usecase);
4885 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4886 popcount(out->channel_mask),
4887 out->playback_started);
4888
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004889 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004890 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004891
Surendar Karkaf51b5842018-04-26 11:28:38 +05304892 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4893 sizeof(value));
4894 if (err >= 0) {
4895 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4896 audio_extn_send_dual_mono_mixing_coefficients(out);
4897 }
4898
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304899 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4900 if (err >= 0) {
4901 strlcpy(out->profile, value, sizeof(out->profile));
4902 ALOGV("updating stream profile with value '%s'", out->profile);
4903 lock_output_stream(out);
4904 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4905 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004906 &out->device_list, out->flags,
4907 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304908 out->sample_rate, out->bit_width,
4909 out->channel_mask, out->profile,
4910 &out->app_type_cfg);
4911 pthread_mutex_unlock(&out->lock);
4912 }
4913
Alexy Joseph98988832017-01-13 14:56:59 -08004914 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004915 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4916 // and vendor.audio.hal.output.suspend.supported is set to true
4917 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004918 //check suspend parameter only for low latency and if the property
4919 //is enabled
4920 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4921 ALOGI("%s: got suspend_playback %s", __func__, value);
4922 lock_output_stream(out);
4923 if (!strncmp(value, "false", 5)) {
4924 //suspend_playback=false is supposed to set QOS value back to 75%
4925 //the mixer control sent with value Enable will achieve that
4926 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4927 } else if (!strncmp (value, "true", 4)) {
4928 //suspend_playback=true is supposed to remove QOS value
4929 //resetting the mixer control will set the default value
4930 //for the mixer control which is Disable and this removes the QOS vote
4931 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4932 } else {
4933 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4934 " got %s", __func__, value);
4935 ret = -1;
4936 }
4937
4938 if (ret != 0) {
4939 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4940 __func__, out->pm_qos_mixer_path, ret);
4941 }
4942
4943 pthread_mutex_unlock(&out->lock);
4944 }
4945 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004946
Alexy Joseph98988832017-01-13 14:56:59 -08004947 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004948 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304949error:
Eric Laurent994a6932013-07-17 11:51:42 -07004950 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004951 return ret;
4952}
4953
Paul McLeana50b7332018-12-17 08:24:21 -07004954static int in_set_microphone_direction(const struct audio_stream_in *stream,
4955 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004956 struct stream_in *in = (struct stream_in *)stream;
4957
4958 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4959
4960 in->direction = dir;
4961
4962 if (in->standby)
4963 return 0;
4964
4965 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004966}
4967
4968static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004969 struct stream_in *in = (struct stream_in *)stream;
4970
4971 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4972
4973 if (zoom > 1.0 || zoom < -1.0)
4974 return -EINVAL;
4975
4976 in->zoom = zoom;
4977
4978 if (in->standby)
4979 return 0;
4980
4981 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004982}
4983
4984
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004985static bool stream_get_parameter_channels(struct str_parms *query,
4986 struct str_parms *reply,
4987 audio_channel_mask_t *supported_channel_masks) {
4988 int ret = -1;
4989 char value[512];
4990 bool first = true;
4991 size_t i, j;
4992
4993 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4994 ret = 0;
4995 value[0] = '\0';
4996 i = 0;
4997 while (supported_channel_masks[i] != 0) {
4998 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4999 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
5000 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305001 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005002
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305003 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005004 first = false;
5005 break;
5006 }
5007 }
5008 i++;
5009 }
5010 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5011 }
5012 return ret == 0;
5013}
5014
5015static bool stream_get_parameter_formats(struct str_parms *query,
5016 struct str_parms *reply,
5017 audio_format_t *supported_formats) {
5018 int ret = -1;
5019 char value[256];
5020 size_t i, j;
5021 bool first = true;
5022
5023 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5024 ret = 0;
5025 value[0] = '\0';
5026 i = 0;
5027 while (supported_formats[i] != 0) {
5028 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5029 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5030 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305031 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005032 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305033 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005034 first = false;
5035 break;
5036 }
5037 }
5038 i++;
5039 }
5040 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5041 }
5042 return ret == 0;
5043}
5044
5045static bool stream_get_parameter_rates(struct str_parms *query,
5046 struct str_parms *reply,
5047 uint32_t *supported_sample_rates) {
5048
5049 int i;
5050 char value[256];
5051 int ret = -1;
5052 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5053 ret = 0;
5054 value[0] = '\0';
5055 i=0;
5056 int cursor = 0;
5057 while (supported_sample_rates[i]) {
5058 int avail = sizeof(value) - cursor;
5059 ret = snprintf(value + cursor, avail, "%s%d",
5060 cursor > 0 ? "|" : "",
5061 supported_sample_rates[i]);
5062 if (ret < 0 || ret >= avail) {
5063 // if cursor is at the last element of the array
5064 // overwrite with \0 is duplicate work as
5065 // snprintf already put a \0 in place.
5066 // else
5067 // we had space to write the '|' at value[cursor]
5068 // (which will be overwritten) or no space to fill
5069 // the first element (=> cursor == 0)
5070 value[cursor] = '\0';
5071 break;
5072 }
5073 cursor += ret;
5074 ++i;
5075 }
5076 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5077 value);
5078 }
5079 return ret >= 0;
5080}
5081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005082static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5083{
5084 struct stream_out *out = (struct stream_out *)stream;
5085 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005086 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005087 char value[256];
5088 struct str_parms *reply = str_parms_create();
5089 size_t i, j;
5090 int ret;
5091 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005092
5093 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005094 if (reply) {
5095 str_parms_destroy(reply);
5096 }
5097 if (query) {
5098 str_parms_destroy(query);
5099 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005100 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5101 return NULL;
5102 }
5103
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005104 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005105 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5106 if (ret >= 0) {
5107 value[0] = '\0';
5108 i = 0;
5109 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005110 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5111 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005112 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005113 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005114 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005115 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005116 first = false;
5117 break;
5118 }
5119 }
5120 i++;
5121 }
5122 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5123 str = str_parms_to_str(reply);
5124 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005125 voice_extn_out_get_parameters(out, query, reply);
5126 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005127 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005128
Alexy Joseph62142aa2015-11-16 15:10:34 -08005129
5130 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5131 if (ret >= 0) {
5132 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305133 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5134 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005135 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305136 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005137 } else {
5138 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305139 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005140 }
5141 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005142 if (str)
5143 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005144 str = str_parms_to_str(reply);
5145 }
5146
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005147 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5148 if (ret >= 0) {
5149 value[0] = '\0';
5150 i = 0;
5151 first = true;
5152 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005153 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5154 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005155 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005156 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005157 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005158 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005159 first = false;
5160 break;
5161 }
5162 }
5163 i++;
5164 }
5165 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005166 if (str)
5167 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005168 str = str_parms_to_str(reply);
5169 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005170
5171 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5172 if (ret >= 0) {
5173 value[0] = '\0';
5174 i = 0;
5175 first = true;
5176 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005177 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5178 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005179 if (!first) {
5180 strlcat(value, "|", sizeof(value));
5181 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005182 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005183 first = false;
5184 break;
5185 }
5186 }
5187 i++;
5188 }
5189 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5190 if (str)
5191 free(str);
5192 str = str_parms_to_str(reply);
5193 }
5194
Alexy Joseph98988832017-01-13 14:56:59 -08005195 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5196 //only low latency track supports suspend_resume
5197 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005198 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005199 if (str)
5200 free(str);
5201 str = str_parms_to_str(reply);
5202 }
5203
5204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005205 str_parms_destroy(query);
5206 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005207 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005208 return str;
5209}
5210
5211static uint32_t out_get_latency(const struct audio_stream_out *stream)
5212{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005213 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005214 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005215 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005216
Alexy Josephaa54c872014-12-03 02:46:47 -08005217 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305218 lock_output_stream(out);
5219 latency = audio_extn_utils_compress_get_dsp_latency(out);
5220 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005221 } else if ((out->realtime) ||
5222 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005223 // since the buffer won't be filled up faster than realtime,
5224 // return a smaller number
5225 if (out->config.rate)
5226 period_ms = (out->af_period_multiplier * out->config.period_size *
5227 1000) / (out->config.rate);
5228 else
5229 period_ms = 0;
5230 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005231 } else {
5232 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005233 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005234 }
5235
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005236 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005237 latency += audio_extn_a2dp_get_encoder_latency();
5238
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305239 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005240 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005241}
5242
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305243static float AmpToDb(float amplification)
5244{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305245 float db = DSD_VOLUME_MIN_DB;
5246 if (amplification > 0) {
5247 db = 20 * log10(amplification);
5248 if(db < DSD_VOLUME_MIN_DB)
5249 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305250 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305251 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305252}
5253
Arun Mirpuri5d170872019-03-26 13:21:31 -07005254static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5255 float right)
5256{
5257 struct stream_out *out = (struct stream_out *)stream;
5258 long volume = 0;
5259 char mixer_ctl_name[128] = "";
5260 struct audio_device *adev = out->dev;
5261 struct mixer_ctl *ctl = NULL;
5262 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5263 PCM_PLAYBACK);
5264
5265 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5266 "Playback %d Volume", pcm_device_id);
5267 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5268 if (!ctl) {
5269 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5270 __func__, mixer_ctl_name);
5271 return -EINVAL;
5272 }
5273 if (left != right)
5274 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5275 __func__, left, right);
5276 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5277 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5278 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5279 __func__, mixer_ctl_name, volume);
5280 return -EINVAL;
5281 }
5282 return 0;
5283}
5284
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305285static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5286 float right)
5287{
5288 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305289 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305290 char mixer_ctl_name[128];
5291 struct audio_device *adev = out->dev;
5292 struct mixer_ctl *ctl;
5293 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5294 PCM_PLAYBACK);
5295
5296 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5297 "Compress Playback %d Volume", pcm_device_id);
5298 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5299 if (!ctl) {
5300 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5301 __func__, mixer_ctl_name);
5302 return -EINVAL;
5303 }
5304 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5305 __func__, mixer_ctl_name, left, right);
5306 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5307 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5308 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5309
5310 return 0;
5311}
5312
Zhou Song2b8f28f2017-09-11 10:51:38 +08005313static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5314 float right)
5315{
5316 struct stream_out *out = (struct stream_out *)stream;
5317 char mixer_ctl_name[] = "App Type Gain";
5318 struct audio_device *adev = out->dev;
5319 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305320 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005321
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005322 if (!is_valid_volume(left, right)) {
5323 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5324 __func__, left, right);
5325 return -EINVAL;
5326 }
5327
Zhou Song2b8f28f2017-09-11 10:51:38 +08005328 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5329 if (!ctl) {
5330 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5331 __func__, mixer_ctl_name);
5332 return -EINVAL;
5333 }
5334
5335 set_values[0] = 0; //0: Rx Session 1:Tx Session
5336 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305337 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5338 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005339
5340 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5341 return 0;
5342}
5343
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305344static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5345 float right)
5346{
5347 struct stream_out *out = (struct stream_out *)stream;
5348 /* Volume control for pcm playback */
5349 if (left != right) {
5350 return -EINVAL;
5351 } else {
5352 char mixer_ctl_name[128];
5353 struct audio_device *adev = out->dev;
5354 struct mixer_ctl *ctl;
5355 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5356 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5357 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5358 if (!ctl) {
5359 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5360 return -EINVAL;
5361 }
5362
5363 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5364 int ret = mixer_ctl_set_value(ctl, 0, volume);
5365 if (ret < 0) {
5366 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5367 return -EINVAL;
5368 }
5369
5370 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5371
5372 return 0;
5373 }
5374}
5375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005376static int out_set_volume(struct audio_stream_out *stream, float left,
5377 float right)
5378{
Eric Laurenta9024de2013-04-04 09:19:12 -07005379 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005380 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305381 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005382
Arun Mirpuri5d170872019-03-26 13:21:31 -07005383 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005384 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5385 /* only take left channel into account: the API is for stereo anyway */
5386 out->muted = (left == 0.0f);
5387 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005388 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305389 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005390 /*
5391 * Set mute or umute on HDMI passthrough stream.
5392 * Only take left channel into account.
5393 * Mute is 0 and unmute 1
5394 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305395 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305396 } else if (out->format == AUDIO_FORMAT_DSD){
5397 char mixer_ctl_name[128] = "DSD Volume";
5398 struct audio_device *adev = out->dev;
5399 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5400
5401 if (!ctl) {
5402 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5403 __func__, mixer_ctl_name);
5404 return -EINVAL;
5405 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305406 volume[0] = (long)(AmpToDb(left));
5407 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305408 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5409 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005410 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005411 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005412 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5413 struct listnode *node = NULL;
5414 list_for_each(node, &adev->active_outputs_list) {
5415 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5416 streams_output_ctxt_t,
5417 list);
5418 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5419 out->volume_l = out_ctxt->output->volume_l;
5420 out->volume_r = out_ctxt->output->volume_r;
5421 }
5422 }
5423 if (!out->a2dp_compress_mute) {
5424 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5425 }
5426 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005427 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305428 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005429 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305430 if (!out->a2dp_compress_mute)
5431 ret = out_set_compr_volume(stream, left, right);
5432 out->volume_l = left;
5433 out->volume_r = right;
5434 pthread_mutex_unlock(&out->compr_mute_lock);
5435 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005436 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005437 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005438 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5439 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5440 if (!out->standby) {
5441 audio_extn_utils_send_app_type_gain(out->dev,
5442 out->app_type_cfg.app_type,
5443 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005444 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005445 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005446 out->volume_l = left;
5447 out->volume_r = right;
5448 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005449 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5450 ALOGV("%s: MMAP set volume called", __func__);
5451 if (!out->standby)
5452 ret = out_set_mmap_volume(stream, left, right);
5453 out->volume_l = left;
5454 out->volume_r = right;
5455 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305456 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305457 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5458 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305459 /* Volume control for pcm playback */
5460 if (!out->standby)
5461 ret = out_set_pcm_volume(stream, left, right);
5462 else
5463 out->apply_volume = true;
5464
5465 out->volume_l = left;
5466 out->volume_r = right;
5467 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005468 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5469 ALOGV("%s: bus device set volume called", __func__);
5470 if (!out->standby)
5471 ret = out_set_pcm_volume(stream, left, right);
5472 out->volume_l = left;
5473 out->volume_r = right;
5474 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005475 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005477 return -ENOSYS;
5478}
5479
Zhou Songc9672822017-08-16 16:01:39 +08005480static void update_frames_written(struct stream_out *out, size_t bytes)
5481{
5482 size_t bpf = 0;
5483
5484 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5485 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5486 bpf = 1;
5487 else if (!is_offload_usecase(out->usecase))
5488 bpf = audio_bytes_per_sample(out->format) *
5489 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005490
5491 pthread_mutex_lock(&out->position_query_lock);
5492 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005493 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005494 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5495 }
5496 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005497}
5498
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005499int split_and_write_audio_haptic_data(struct stream_out *out,
5500 const void *buffer, size_t bytes_to_write)
5501{
5502 struct audio_device *adev = out->dev;
5503
5504 int ret = 0;
5505 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5506 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5507 size_t frame_size = channel_count * bytes_per_sample;
5508 size_t frame_count = bytes_to_write / frame_size;
5509
5510 bool force_haptic_path =
5511 property_get_bool("vendor.audio.test_haptic", false);
5512
5513 // extract Haptics data from Audio buffer
5514 bool alloc_haptic_buffer = false;
5515 int haptic_channel_count = adev->haptics_config.channels;
5516 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5517 size_t audio_frame_size = frame_size - haptic_frame_size;
5518 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5519
5520 if (adev->haptic_buffer == NULL) {
5521 alloc_haptic_buffer = true;
5522 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5523 free(adev->haptic_buffer);
5524 adev->haptic_buffer_size = 0;
5525 alloc_haptic_buffer = true;
5526 }
5527
5528 if (alloc_haptic_buffer) {
5529 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005530 if(adev->haptic_buffer == NULL) {
5531 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5532 return -ENOMEM;
5533 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005534 adev->haptic_buffer_size = total_haptic_buffer_size;
5535 }
5536
5537 size_t src_index = 0, aud_index = 0, hap_index = 0;
5538 uint8_t *audio_buffer = (uint8_t *)buffer;
5539 uint8_t *haptic_buffer = adev->haptic_buffer;
5540
5541 // This is required for testing only. This works for stereo data only.
5542 // One channel is fed to audio stream and other to haptic stream for testing.
5543 if (force_haptic_path)
5544 audio_frame_size = haptic_frame_size = bytes_per_sample;
5545
5546 for (size_t i = 0; i < frame_count; i++) {
5547 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5548 audio_frame_size);
5549 aud_index += audio_frame_size;
5550 src_index += audio_frame_size;
5551
5552 if (adev->haptic_pcm)
5553 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5554 haptic_frame_size);
5555 hap_index += haptic_frame_size;
5556 src_index += haptic_frame_size;
5557
5558 // This is required for testing only.
5559 // Discard haptic channel data.
5560 if (force_haptic_path)
5561 src_index += haptic_frame_size;
5562 }
5563
5564 // write to audio pipeline
5565 ret = pcm_write(out->pcm, (void *)audio_buffer,
5566 frame_count * audio_frame_size);
5567
5568 // write to haptics pipeline
5569 if (adev->haptic_pcm)
5570 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5571 frame_count * haptic_frame_size);
5572
5573 return ret;
5574}
5575
Aalique Grahame22e49102018-12-18 14:23:57 -08005576#ifdef NO_AUDIO_OUT
5577static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5578 const void *buffer __unused, size_t bytes)
5579{
5580 struct stream_out *out = (struct stream_out *)stream;
5581
5582 /* No Output device supported other than BT for playback.
5583 * Sleep for the amount of buffer duration
5584 */
5585 lock_output_stream(out);
5586 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5587 (const struct audio_stream_out *)&out->stream) /
5588 out_get_sample_rate(&out->stream.common));
5589 pthread_mutex_unlock(&out->lock);
5590 return bytes;
5591}
5592#endif
5593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005594static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5595 size_t bytes)
5596{
5597 struct stream_out *out = (struct stream_out *)stream;
5598 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005599 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305600 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005601 const size_t frame_size = audio_stream_out_frame_size(stream);
5602 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305603 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005604 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005605
Haynes Mathew George380745d2017-10-04 15:27:45 -07005606 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005607 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305608
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305609 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005610
Dhananjay Kumarac341582017-02-23 23:42:25 +05305611 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305612 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305613 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5614 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005615 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305616 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305617 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305618 ALOGD(" %s: sound card is not active/SSR state", __func__);
5619 ret= -EIO;
5620 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305621 }
5622 }
5623
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305624 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305625 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305626 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305627 goto exit;
5628 }
5629
Haynes Mathew George16081042017-05-31 17:16:49 -07005630 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5631 ret = -EINVAL;
5632 goto exit;
5633 }
5634
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005635 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305636 !out->is_iec61937_info_available) {
5637
5638 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5639 out->is_iec61937_info_available = true;
5640 } else if (audio_extn_passthru_is_enabled()) {
5641 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305642 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305643
5644 if((out->format == AUDIO_FORMAT_DTS) ||
5645 (out->format == AUDIO_FORMAT_DTS_HD)) {
5646 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5647 buffer, bytes);
5648 if (ret) {
5649 if (ret != -ENOSYS) {
5650 out->is_iec61937_info_available = false;
5651 ALOGD("iec61937 transmission info not yet updated retry");
5652 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305653 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305654 /* if stream has started and after that there is
5655 * stream config change (iec transmission config)
5656 * then trigger select_device to update backend configuration.
5657 */
5658 out->stream_config_changed = true;
5659 pthread_mutex_lock(&adev->lock);
5660 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305661 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005662 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305663 ret = -EINVAL;
5664 goto exit;
5665 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305666 pthread_mutex_unlock(&adev->lock);
5667 out->stream_config_changed = false;
5668 out->is_iec61937_info_available = true;
5669 }
5670 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305671
Meng Wang4c32fb42020-01-16 17:57:11 +08005672#ifdef AUDIO_GKI_ENABLED
5673 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5674 compr_passthr = out->compr_config.codec->reserved[0];
5675#else
5676 compr_passthr = out->compr_config.codec->compr_passthr;
5677#endif
5678
Garmond Leung317cbf12017-09-13 16:20:50 -07005679 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005680 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305681 (out->is_iec61937_info_available == true)) {
5682 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5683 ret = -EINVAL;
5684 goto exit;
5685 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305686 }
5687 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305688
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005689 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005690 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005691 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5692 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305693 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305694 ret = -EIO;
5695 goto exit;
5696 }
5697 }
5698 }
5699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005700 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005701 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005702 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005703 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5704 ret = voice_extn_compress_voip_start_output_stream(out);
5705 else
5706 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005707 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005708 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005709 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005710 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005711 goto exit;
5712 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305713 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005714 if (last_known_cal_step != -1) {
5715 ALOGD("%s: retry previous failed cal level set", __func__);
5716 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305717 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005718 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305719
5720 if ((out->is_iec61937_info_available == true) &&
5721 (audio_extn_passthru_is_passthrough_stream(out))&&
5722 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5723 ret = -EINVAL;
5724 goto exit;
5725 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305726 if (out->set_dual_mono)
5727 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005728 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005729
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005730 if (adev->is_channel_status_set == false &&
5731 compare_device_type(&out->device_list,
5732 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005733 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305734 adev->is_channel_status_set = true;
5735 }
5736
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305737 if ((adev->use_old_pspd_mix_ctrl == true) &&
5738 (out->pspd_coeff_sent == false)) {
5739 /*
5740 * Need to resend pspd coefficients after stream started for
5741 * older kernel version as it does not save the coefficients
5742 * and also stream has to be started for coeff to apply.
5743 */
5744 usecase = get_usecase_from_list(adev, out->usecase);
5745 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305746 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305747 out->pspd_coeff_sent = true;
5748 }
5749 }
5750
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005751 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005752 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005753 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005754 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005755 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5756 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305757 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5758 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005759 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305760 out->send_next_track_params = false;
5761 out->is_compr_metadata_avail = false;
5762 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005763 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305764 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305765 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005766
Ashish Jain83a6cc22016-06-28 14:34:17 +05305767 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305768 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305769 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305770 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005771 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305772 return -EINVAL;
5773 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305774 audio_format_t dst_format = out->hal_op_format;
5775 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305776
Dieter Luecking5d57def2018-09-07 14:23:37 +02005777 /* prevent division-by-zero */
5778 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5779 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5780 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5781 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305782 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005783 ATRACE_END();
5784 return -EINVAL;
5785 }
5786
Ashish Jainf1eaa582016-05-23 20:54:24 +05305787 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5788 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5789
Ashish Jain83a6cc22016-06-28 14:34:17 +05305790 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305791 dst_format,
5792 buffer,
5793 src_format,
5794 frames);
5795
Ashish Jain83a6cc22016-06-28 14:34:17 +05305796 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305797 bytes_to_write);
5798
5799 /*Convert written bytes in audio flinger format*/
5800 if (ret > 0)
5801 ret = ((ret * format_to_bitwidth_table[out->format]) /
5802 format_to_bitwidth_table[dst_format]);
5803 }
5804 } else
5805 ret = compress_write(out->compr, buffer, bytes);
5806
Zhou Songc9672822017-08-16 16:01:39 +08005807 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5808 update_frames_written(out, bytes);
5809
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305810 if (ret < 0)
5811 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005812 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305813 /*msg to cb thread only if non blocking write is enabled*/
5814 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305815 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005816 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305817 } else if (-ENETRESET == ret) {
5818 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305819 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305820 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305821 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005822 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305823 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005824 }
Ashish Jain5106d362016-05-11 19:23:33 +05305825
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305826 /* Call compr start only when non-zero bytes of data is there to be rendered */
5827 if (!out->playback_started && ret > 0) {
5828 int status = compress_start(out->compr);
5829 if (status < 0) {
5830 ret = status;
5831 ALOGE("%s: compr start failed with err %d", __func__, errno);
5832 goto exit;
5833 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005834 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005835 out->playback_started = 1;
5836 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005837
5838 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5839 popcount(out->channel_mask),
5840 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005841 }
5842 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005843 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005844 return ret;
5845 } else {
5846 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005847 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005848 if (out->muted)
5849 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005850 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5851 __func__, frames, frame_size, bytes_to_write);
5852
Aalique Grahame22e49102018-12-18 14:23:57 -08005853 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005854 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5855 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5856 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005857 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5858 int16_t *src = (int16_t *)buffer;
5859 int16_t *dst = (int16_t *)buffer;
5860
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005861 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005862 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005863 "out_write called for %s use case with wrong properties",
5864 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005865
5866 /*
5867 * FIXME: this can be removed once audio flinger mixer supports
5868 * mono output
5869 */
5870
5871 /*
5872 * Code below goes over each frame in the buffer and adds both
5873 * L and R samples and then divides by 2 to convert to mono
5874 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005875 if (channel_count == 2) {
5876 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5877 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5878 }
5879 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005880 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005881 }
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305882 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005883
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005884 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005885
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005886 if (out->config.rate)
5887 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5888 out->config.rate;
5889
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005890 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005891 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5892
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005893 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005894 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005895 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305896 out->convert_buffer != NULL) {
5897
5898 memcpy_by_audio_format(out->convert_buffer,
5899 out->hal_op_format,
5900 buffer,
5901 out->hal_ip_format,
5902 out->config.period_size * out->config.channels);
5903
5904 ret = pcm_write(out->pcm, out->convert_buffer,
5905 (out->config.period_size *
5906 out->config.channels *
5907 format_to_bitwidth_table[out->hal_op_format]));
5908 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305909 /*
5910 * To avoid underrun in DSP when the application is not pumping
5911 * data at required rate, check for the no. of bytes and ignore
5912 * pcm_write if it is less than actual buffer size.
5913 * It is a work around to a change in compress VOIP driver.
5914 */
5915 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5916 bytes < (out->config.period_size * out->config.channels *
5917 audio_bytes_per_sample(out->format))) {
5918 size_t voip_buf_size =
5919 out->config.period_size * out->config.channels *
5920 audio_bytes_per_sample(out->format);
5921 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5922 __func__, bytes, voip_buf_size);
5923 usleep(((uint64_t)voip_buf_size - bytes) *
5924 1000000 / audio_stream_out_frame_size(stream) /
5925 out_get_sample_rate(&out->stream.common));
5926 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005927 } else {
5928 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5929 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5930 else
5931 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5932 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305933 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005934
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005935 release_out_focus(out);
5936
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305937 if (ret < 0)
5938 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005939 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305940 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005941 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005942 }
5943
5944exit:
Zhou Songc9672822017-08-16 16:01:39 +08005945 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305946 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305947 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305948 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005949 pthread_mutex_unlock(&out->lock);
5950
5951 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005952 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005953 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305954 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305955 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305956 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305957 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305958 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305959 out->standby = true;
5960 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305961 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005962 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5963 /* prevent division-by-zero */
5964 uint32_t stream_size = audio_stream_out_frame_size(stream);
5965 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005966
Dieter Luecking5d57def2018-09-07 14:23:37 +02005967 if ((stream_size == 0) || (srate == 0)) {
5968 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5969 ATRACE_END();
5970 return -EINVAL;
5971 }
5972 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5973 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005974 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305975 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005976 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005977 return ret;
5978 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005979 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005980 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005981 return bytes;
5982}
5983
5984static int out_get_render_position(const struct audio_stream_out *stream,
5985 uint32_t *dsp_frames)
5986{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005987 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005988
5989 if (dsp_frames == NULL)
5990 return -EINVAL;
5991
5992 *dsp_frames = 0;
5993 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005994 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305995
5996 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5997 * this operation and adev_close_output_stream(where out gets reset).
5998 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305999 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006000 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306001 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006002 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306003 return 0;
6004 }
6005
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006006 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306007 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306008 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006009 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306010 if (ret < 0)
6011 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006012 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306013 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006014 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306015 if (-ENETRESET == ret) {
6016 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306017 out->card_status = CARD_STATUS_OFFLINE;
6018 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306019 } else if(ret < 0) {
6020 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306021 ret = -EINVAL;
6022 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306023 /*
6024 * Handle corner case where compress session is closed during SSR
6025 * and timestamp is queried
6026 */
6027 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306028 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306029 } else if (out->prev_card_status_offline) {
6030 ALOGE("ERROR: previously sound card was offline,return error");
6031 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306032 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306033 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006034 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306035 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306036 pthread_mutex_unlock(&out->lock);
6037 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006038 } else if (audio_is_linear_pcm(out->format)) {
6039 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006040 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006041 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006042 } else
6043 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006044}
6045
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006046static int out_add_audio_effect(const struct audio_stream *stream __unused,
6047 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006048{
6049 return 0;
6050}
6051
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006052static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6053 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006054{
6055 return 0;
6056}
6057
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006058static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6059 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006060{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306061 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006062}
6063
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006064static int out_get_presentation_position(const struct audio_stream_out *stream,
6065 uint64_t *frames, struct timespec *timestamp)
6066{
6067 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306068 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006069 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006070
Ashish Jain5106d362016-05-11 19:23:33 +05306071 /* below piece of code is not guarded against any lock because audioFliner serializes
6072 * this operation and adev_close_output_stream( where out gets reset).
6073 */
6074 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306075 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006076 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306077 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6078 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6079 return 0;
6080 }
6081
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006082 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006083
Ashish Jain5106d362016-05-11 19:23:33 +05306084 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6085 ret = compress_get_tstamp(out->compr, &dsp_frames,
6086 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006087 // Adjustment accounts for A2dp encoder latency with offload usecases
6088 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006089 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006090 unsigned long offset =
6091 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6092 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6093 }
Ashish Jain5106d362016-05-11 19:23:33 +05306094 ALOGVV("%s rendered frames %ld sample_rate %d",
6095 __func__, dsp_frames, out->sample_rate);
6096 *frames = dsp_frames;
6097 if (ret < 0)
6098 ret = -errno;
6099 if (-ENETRESET == ret) {
6100 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306101 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306102 ret = -EINVAL;
6103 } else
6104 ret = 0;
6105 /* this is the best we can do */
6106 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006107 } else {
6108 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006109 unsigned int avail;
6110 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
6111 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
George Gao62ebc722019-07-29 16:29:44 -07006112
6113 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006114 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006115
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006116 frames_temp = (kernel_buffer_size > avail) ? (kernel_buffer_size - avail) : 0;
6117 if (out->written >= frames_temp)
6118 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006119
Weiyin Jiangd4633762018-03-16 12:05:03 +08006120 // This adjustment accounts for buffering after app processor.
6121 // It is based on estimated DSP latency per use case, rather than exact.
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006122 frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL;
6123 if (signed_frames >= frames_temp)
6124 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006125
Weiyin Jiangd4633762018-03-16 12:05:03 +08006126 // Adjustment accounts for A2dp encoder latency with non offload usecases
6127 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006128 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006129 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6130 if (signed_frames >= frames_temp)
6131 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006132 }
6133
6134 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006135 *frames = signed_frames;
6136 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006137 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306138 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306139 *frames = out->written;
6140 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306141 if (is_offload_usecase(out->usecase))
6142 ret = -EINVAL;
6143 else
6144 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006145 }
6146 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006147 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006148 return ret;
6149}
6150
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006151static int out_set_callback(struct audio_stream_out *stream,
6152 stream_callback_t callback, void *cookie)
6153{
6154 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006155 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006156
6157 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006158 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006159 out->client_callback = callback;
6160 out->client_cookie = cookie;
6161 if (out->adsp_hdlr_stream_handle) {
6162 ret = audio_extn_adsp_hdlr_stream_set_callback(
6163 out->adsp_hdlr_stream_handle,
6164 callback,
6165 cookie);
6166 if (ret)
6167 ALOGW("%s:adsp hdlr callback registration failed %d",
6168 __func__, ret);
6169 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006170 pthread_mutex_unlock(&out->lock);
6171 return 0;
6172}
6173
6174static int out_pause(struct audio_stream_out* stream)
6175{
6176 struct stream_out *out = (struct stream_out *)stream;
6177 int status = -ENOSYS;
6178 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006179 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006180 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006181 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006182 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306183 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306184 status = compress_pause(out->compr);
6185
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006186 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006187
Mingming Yin21854652016-04-13 11:54:02 -07006188 if (audio_extn_passthru_is_active()) {
6189 ALOGV("offload use case, pause passthru");
6190 audio_extn_passthru_on_pause(out);
6191 }
6192
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306193 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006194 audio_extn_dts_notify_playback_state(out->usecase, 0,
6195 out->sample_rate, popcount(out->channel_mask),
6196 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006197 }
6198 pthread_mutex_unlock(&out->lock);
6199 }
6200 return status;
6201}
6202
6203static int out_resume(struct audio_stream_out* stream)
6204{
6205 struct stream_out *out = (struct stream_out *)stream;
6206 int status = -ENOSYS;
6207 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006208 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006209 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006210 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006211 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006212 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306213 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306214 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006215 }
6216 if (!status) {
6217 out->offload_state = OFFLOAD_STATE_PLAYING;
6218 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306219 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006220 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6221 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006222 }
6223 pthread_mutex_unlock(&out->lock);
6224 }
6225 return status;
6226}
6227
6228static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6229{
6230 struct stream_out *out = (struct stream_out *)stream;
6231 int status = -ENOSYS;
6232 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006233 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006234 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006235 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6236 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6237 else
6238 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6239 pthread_mutex_unlock(&out->lock);
6240 }
6241 return status;
6242}
6243
6244static int out_flush(struct audio_stream_out* stream)
6245{
6246 struct stream_out *out = (struct stream_out *)stream;
6247 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006248 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006249 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006250 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006251 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6252 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006253 } else {
6254 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6255 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006256 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006257 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006258 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006259 return 0;
6260 }
6261 return -ENOSYS;
6262}
6263
Haynes Mathew George16081042017-05-31 17:16:49 -07006264static int out_stop(const struct audio_stream_out* stream)
6265{
6266 struct stream_out *out = (struct stream_out *)stream;
6267 struct audio_device *adev = out->dev;
6268 int ret = -ENOSYS;
6269
6270 ALOGV("%s", __func__);
6271 pthread_mutex_lock(&adev->lock);
6272 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6273 out->playback_started && out->pcm != NULL) {
6274 pcm_stop(out->pcm);
6275 ret = stop_output_stream(out);
6276 out->playback_started = false;
6277 }
6278 pthread_mutex_unlock(&adev->lock);
6279 return ret;
6280}
6281
6282static int out_start(const struct audio_stream_out* stream)
6283{
6284 struct stream_out *out = (struct stream_out *)stream;
6285 struct audio_device *adev = out->dev;
6286 int ret = -ENOSYS;
6287
6288 ALOGV("%s", __func__);
6289 pthread_mutex_lock(&adev->lock);
6290 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6291 !out->playback_started && out->pcm != NULL) {
6292 ret = start_output_stream(out);
6293 if (ret == 0) {
6294 out->playback_started = true;
6295 }
6296 }
6297 pthread_mutex_unlock(&adev->lock);
6298 return ret;
6299}
6300
6301/*
6302 * Modify config->period_count based on min_size_frames
6303 */
6304static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6305{
6306 int periodCountRequested = (min_size_frames + config->period_size - 1)
6307 / config->period_size;
6308 int periodCount = MMAP_PERIOD_COUNT_MIN;
6309
6310 ALOGV("%s original config.period_size = %d config.period_count = %d",
6311 __func__, config->period_size, config->period_count);
6312
6313 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6314 periodCount *= 2;
6315 }
6316 config->period_count = periodCount;
6317
6318 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6319}
6320
Phil Burkfe17efd2019-03-25 10:23:35 -07006321// Read offset for the positional timestamp from a persistent vendor property.
6322// This is to workaround apparent inaccuracies in the timing information that
6323// is used by the AAudio timing model. The inaccuracies can cause glitches.
6324static int64_t get_mmap_out_time_offset() {
6325 const int32_t kDefaultOffsetMicros = 0;
6326 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006327 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006328 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6329 return mmap_time_offset_micros * (int64_t)1000;
6330}
6331
Haynes Mathew George16081042017-05-31 17:16:49 -07006332static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6333 int32_t min_size_frames,
6334 struct audio_mmap_buffer_info *info)
6335{
6336 struct stream_out *out = (struct stream_out *)stream;
6337 struct audio_device *adev = out->dev;
6338 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006339 unsigned int offset1 = 0;
6340 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006341 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006342 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006343 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006344
Arun Mirpuri5d170872019-03-26 13:21:31 -07006345 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306346 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006347 pthread_mutex_lock(&adev->lock);
6348
Sharad Sanglec6f32552018-05-04 16:15:38 +05306349 if (CARD_STATUS_OFFLINE == out->card_status ||
6350 CARD_STATUS_OFFLINE == adev->card_status) {
6351 ALOGW("out->card_status or adev->card_status offline, try again");
6352 ret = -EIO;
6353 goto exit;
6354 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006355 if (info == NULL || min_size_frames == 0) {
6356 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6357 ret = -EINVAL;
6358 goto exit;
6359 }
6360 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6361 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6362 ret = -ENOSYS;
6363 goto exit;
6364 }
6365 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6366 if (out->pcm_device_id < 0) {
6367 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6368 __func__, out->pcm_device_id, out->usecase);
6369 ret = -EINVAL;
6370 goto exit;
6371 }
6372
6373 adjust_mmap_period_count(&out->config, min_size_frames);
6374
Arun Mirpuri5d170872019-03-26 13:21:31 -07006375 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006376 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6377 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6378 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306379 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306380 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6381 out->card_status = CARD_STATUS_OFFLINE;
6382 adev->card_status = CARD_STATUS_OFFLINE;
6383 ret = -EIO;
6384 goto exit;
6385 }
6386
Haynes Mathew George16081042017-05-31 17:16:49 -07006387 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6388 step = "open";
6389 ret = -ENODEV;
6390 goto exit;
6391 }
6392 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6393 if (ret < 0) {
6394 step = "begin";
6395 goto exit;
6396 }
6397 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006398 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006399 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006400 ret = platform_get_mmap_data_fd(adev->platform,
6401 out->pcm_device_id, 0 /*playback*/,
6402 &info->shared_memory_fd,
6403 &mmap_size);
6404 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006405 // Fall back to non exclusive mode
6406 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6407 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006408 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6409 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6410
Arun Mirpuri5d170872019-03-26 13:21:31 -07006411 if (mmap_size < buffer_size) {
6412 step = "mmap";
6413 goto exit;
6414 }
6415 // FIXME: indicate exclusive mode support by returning a negative buffer size
6416 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006417 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006418 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006419 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006420
6421 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6422 if (ret < 0) {
6423 step = "commit";
6424 goto exit;
6425 }
6426
Phil Burkfe17efd2019-03-25 10:23:35 -07006427 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6428
Haynes Mathew George16081042017-05-31 17:16:49 -07006429 out->standby = false;
6430 ret = 0;
6431
Arun Mirpuri5d170872019-03-26 13:21:31 -07006432 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006433 __func__, info->shared_memory_address, info->buffer_size_frames);
6434
6435exit:
6436 if (ret != 0) {
6437 if (out->pcm == NULL) {
6438 ALOGE("%s: %s - %d", __func__, step, ret);
6439 } else {
6440 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6441 pcm_close(out->pcm);
6442 out->pcm = NULL;
6443 }
6444 }
6445 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306446 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006447 return ret;
6448}
6449
6450static int out_get_mmap_position(const struct audio_stream_out *stream,
6451 struct audio_mmap_position *position)
6452{
6453 struct stream_out *out = (struct stream_out *)stream;
6454 ALOGVV("%s", __func__);
6455 if (position == NULL) {
6456 return -EINVAL;
6457 }
6458 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006459 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006460 return -ENOSYS;
6461 }
6462 if (out->pcm == NULL) {
6463 return -ENOSYS;
6464 }
6465
6466 struct timespec ts = { 0, 0 };
6467 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6468 if (ret < 0) {
6469 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6470 return ret;
6471 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006472 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6473 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006474 return 0;
6475}
6476
6477
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006478/** audio_stream_in implementation **/
6479static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6480{
6481 struct stream_in *in = (struct stream_in *)stream;
6482
6483 return in->config.rate;
6484}
6485
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006486static int in_set_sample_rate(struct audio_stream *stream __unused,
6487 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006488{
6489 return -ENOSYS;
6490}
6491
6492static size_t in_get_buffer_size(const struct audio_stream *stream)
6493{
6494 struct stream_in *in = (struct stream_in *)stream;
6495
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006496 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6497 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006498 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6499 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306500 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306501 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006502
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006503 return in->config.period_size * in->af_period_multiplier *
6504 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006505}
6506
6507static uint32_t in_get_channels(const struct audio_stream *stream)
6508{
6509 struct stream_in *in = (struct stream_in *)stream;
6510
6511 return in->channel_mask;
6512}
6513
6514static audio_format_t in_get_format(const struct audio_stream *stream)
6515{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006516 struct stream_in *in = (struct stream_in *)stream;
6517
6518 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006519}
6520
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006521static int in_set_format(struct audio_stream *stream __unused,
6522 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006523{
6524 return -ENOSYS;
6525}
6526
6527static int in_standby(struct audio_stream *stream)
6528{
6529 struct stream_in *in = (struct stream_in *)stream;
6530 struct audio_device *adev = in->dev;
6531 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306532 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6533 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006534 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306535
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006536 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006537 if (!in->standby && in->is_st_session) {
6538 ALOGD("%s: sound trigger pcm stop lab", __func__);
6539 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006540 if (adev->num_va_sessions > 0)
6541 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006542 in->standby = 1;
6543 }
6544
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006545 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006546 if (adev->adm_deregister_stream)
6547 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6548
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006549 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006550 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006551 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006552 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006553 voice_extn_compress_voip_close_input_stream(stream);
6554 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006555 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6556 do_stop = in->capture_started;
6557 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006558 if (in->mmap_shared_memory_fd >= 0) {
6559 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6560 __func__, in->mmap_shared_memory_fd);
6561 close(in->mmap_shared_memory_fd);
6562 in->mmap_shared_memory_fd = -1;
6563 }
Zhou Songa8895042016-07-05 17:54:22 +08006564 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306565 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306566 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006567 }
6568
Arun Mirpuri5d170872019-03-26 13:21:31 -07006569 if (in->pcm) {
6570 ATRACE_BEGIN("pcm_in_close");
6571 pcm_close(in->pcm);
6572 ATRACE_END();
6573 in->pcm = NULL;
6574 }
6575
Carter Hsu2e429db2019-05-14 18:50:52 +08006576 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006577 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006578
George Gao3018ede2019-10-23 13:23:00 -07006579 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6580 if (adev->num_va_sessions > 0)
6581 adev->num_va_sessions--;
6582 }
Quinn Malef6050362019-01-30 15:55:40 -08006583
Eric Laurent150dbfe2013-02-27 14:31:02 -08006584 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006585 }
6586 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006587 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006588 return status;
6589}
6590
Aalique Grahame22e49102018-12-18 14:23:57 -08006591static int in_dump(const struct audio_stream *stream,
6592 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006593{
Aalique Grahame22e49102018-12-18 14:23:57 -08006594 struct stream_in *in = (struct stream_in *)stream;
6595
6596 // We try to get the lock for consistency,
6597 // but it isn't necessary for these variables.
6598 // If we're not in standby, we may be blocked on a read.
6599 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6600 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6601 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6602 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6603
6604 if (locked) {
6605 pthread_mutex_unlock(&in->lock);
6606 }
6607
6608 // dump error info
6609 (void)error_log_dump(
6610 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006612 return 0;
6613}
6614
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306615static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6616{
6617 if (!stream || !parms)
6618 return;
6619
6620 struct stream_in *in = (struct stream_in *)stream;
6621 struct audio_device *adev = in->dev;
6622
6623 card_status_t status;
6624 int card;
6625 if (parse_snd_card_status(parms, &card, &status) < 0)
6626 return;
6627
6628 pthread_mutex_lock(&adev->lock);
6629 bool valid_cb = (card == adev->snd_card);
6630 pthread_mutex_unlock(&adev->lock);
6631
6632 if (!valid_cb)
6633 return;
6634
6635 lock_input_stream(in);
6636 if (in->card_status != status)
6637 in->card_status = status;
6638 pthread_mutex_unlock(&in->lock);
6639
6640 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6641 use_case_table[in->usecase],
6642 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6643
6644 // a better solution would be to report error back to AF and let
6645 // it put the stream to standby
6646 if (status == CARD_STATUS_OFFLINE)
6647 in_standby(&in->stream.common);
6648
6649 return;
6650}
6651
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006652int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006653 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006654 audio_source_t source)
6655{
6656 struct audio_device *adev = in->dev;
6657 int ret = 0;
6658
6659 lock_input_stream(in);
6660 pthread_mutex_lock(&adev->lock);
6661
6662 /* no audio source uses val == 0 */
6663 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6664 in->source = source;
6665 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6666 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6667 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6668 (in->config.rate == 8000 || in->config.rate == 16000 ||
6669 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6670 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6671 ret = voice_extn_compress_voip_open_input_stream(in);
6672 if (ret != 0) {
6673 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6674 __func__, ret);
6675 }
6676 }
6677 }
6678
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006679 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6680 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006681 // Workaround: If routing to an non existing usb device, fail gracefully
6682 // The routing request will otherwise block during 10 second
6683 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006684 struct str_parms *usb_addr =
6685 str_parms_create_str(get_usb_device_address(devices));
6686 if (is_usb_in_device_type(devices) && usb_addr &&
6687 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006688 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6689 ret = -ENOSYS;
6690 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006691 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006692 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006693 if (!in->standby && !in->is_st_session) {
6694 ALOGV("update input routing change");
6695 // inform adm before actual routing to prevent glitches.
6696 if (adev->adm_on_routing_change) {
6697 adev->adm_on_routing_change(adev->adm_data,
6698 in->capture_handle);
6699 ret = select_devices(adev, in->usecase);
6700 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6701 adev->adm_routing_changed = true;
6702 }
6703 }
6704 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006705 if (usb_addr)
6706 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006707 }
6708 pthread_mutex_unlock(&adev->lock);
6709 pthread_mutex_unlock(&in->lock);
6710
6711 ALOGD("%s: exit: status(%d)", __func__, ret);
6712 return ret;
6713}
6714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006715static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6716{
6717 struct stream_in *in = (struct stream_in *)stream;
6718 struct audio_device *adev = in->dev;
6719 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006720 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006721 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006722
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306723 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006724 parms = str_parms_create_str(kvpairs);
6725
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306726 if (!parms)
6727 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006728 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006729 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006730
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006731 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6732 if (ret >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306733 strlcpy(in->profile, value, sizeof(in->profile));
6734 ALOGV("updating stream profile with value '%s'", in->profile);
6735 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6736 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006737 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306738 in->sample_rate, in->bit_width,
6739 in->profile, &in->app_type_cfg);
6740 }
6741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006742 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006743 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006744
6745 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306746error:
Eric Laurent994a6932013-07-17 11:51:42 -07006747 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006748 return ret;
6749}
6750
6751static char* in_get_parameters(const struct audio_stream *stream,
6752 const char *keys)
6753{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006754 struct stream_in *in = (struct stream_in *)stream;
6755 struct str_parms *query = str_parms_create_str(keys);
6756 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006757 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006758
6759 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006760 if (reply) {
6761 str_parms_destroy(reply);
6762 }
6763 if (query) {
6764 str_parms_destroy(query);
6765 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006766 ALOGE("in_get_parameters: failed to create query or reply");
6767 return NULL;
6768 }
6769
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006770 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006771
6772 voice_extn_in_get_parameters(in, query, reply);
6773
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006774 stream_get_parameter_channels(query, reply,
6775 &in->supported_channel_masks[0]);
6776 stream_get_parameter_formats(query, reply,
6777 &in->supported_formats[0]);
6778 stream_get_parameter_rates(query, reply,
6779 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006780 str = str_parms_to_str(reply);
6781 str_parms_destroy(query);
6782 str_parms_destroy(reply);
6783
6784 ALOGV("%s: exit: returns - %s", __func__, str);
6785 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006786}
6787
Aalique Grahame22e49102018-12-18 14:23:57 -08006788static int in_set_gain(struct audio_stream_in *stream,
6789 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006790{
Aalique Grahame22e49102018-12-18 14:23:57 -08006791 struct stream_in *in = (struct stream_in *)stream;
6792 char mixer_ctl_name[128];
6793 struct mixer_ctl *ctl;
6794 int ctl_value;
6795
6796 ALOGV("%s: gain %f", __func__, gain);
6797
6798 if (stream == NULL)
6799 return -EINVAL;
6800
6801 /* in_set_gain() only used to silence MMAP capture for now */
6802 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6803 return -ENOSYS;
6804
6805 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6806
6807 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6808 if (!ctl) {
6809 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6810 __func__, mixer_ctl_name);
6811 return -ENOSYS;
6812 }
6813
6814 if (gain < RECORD_GAIN_MIN)
6815 gain = RECORD_GAIN_MIN;
6816 else if (gain > RECORD_GAIN_MAX)
6817 gain = RECORD_GAIN_MAX;
6818 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6819
6820 mixer_ctl_set_value(ctl, 0, ctl_value);
6821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006822 return 0;
6823}
6824
6825static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6826 size_t bytes)
6827{
6828 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306829
6830 if (in == NULL) {
6831 ALOGE("%s: stream_in ptr is NULL", __func__);
6832 return -EINVAL;
6833 }
6834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006835 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306836 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306837 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006838
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006839 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306840
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006841 if (in->is_st_session) {
6842 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6843 /* Read from sound trigger HAL */
6844 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006845 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006846 if (adev->num_va_sessions < UINT_MAX)
6847 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006848 in->standby = 0;
6849 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006850 pthread_mutex_unlock(&in->lock);
6851 return bytes;
6852 }
6853
Haynes Mathew George16081042017-05-31 17:16:49 -07006854 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6855 ret = -ENOSYS;
6856 goto exit;
6857 }
6858
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006859 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6860 !in->standby && adev->adm_routing_changed) {
6861 ret = -ENOSYS;
6862 goto exit;
6863 }
6864
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006865 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006866 pthread_mutex_lock(&adev->lock);
6867 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6868 ret = voice_extn_compress_voip_start_input_stream(in);
6869 else
6870 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006871 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6872 if (adev->num_va_sessions < UINT_MAX)
6873 adev->num_va_sessions++;
6874 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006875 pthread_mutex_unlock(&adev->lock);
6876 if (ret != 0) {
6877 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006878 }
6879 in->standby = 0;
6880 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006881
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306882 /* Avoid read if capture_stopped is set */
6883 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6884 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6885 ret = -EINVAL;
6886 goto exit;
6887 }
6888
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006889 // what's the duration requested by the client?
6890 long ns = 0;
6891
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306892 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006893 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6894 in->config.rate;
6895
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006896 ret = request_in_focus(in, ns);
6897 if (ret != 0)
6898 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006899 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006900
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306901 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306902 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6903 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306904 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006905 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306906 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006907 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006908 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006909 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006910 } else if (audio_extn_ffv_get_stream() == in) {
6911 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306912 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006913 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306914 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6915 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6916 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6917 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306918 ret = -EINVAL;
6919 goto exit;
6920 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306921 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306922 ret = -errno;
6923 }
6924 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306925 /* bytes read is always set to bytes for non compress usecases */
6926 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006927 }
6928
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006929 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006931 /*
Quinn Malef6050362019-01-30 15:55:40 -08006932 * Instead of writing zeroes here, we could trust the hardware to always
6933 * provide zeroes when muted. This is also muted with voice recognition
6934 * usecases so that other clients do not have access to voice recognition
6935 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006936 */
Quinn Malef6050362019-01-30 15:55:40 -08006937 if ((ret == 0 && voice_get_mic_mute(adev) &&
6938 !voice_is_in_call_rec_stream(in) &&
6939 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6940 (adev->num_va_sessions &&
6941 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6942 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6943 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006944 memset(buffer, 0, bytes);
6945
6946exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306947 frame_size = audio_stream_in_frame_size(stream);
6948 if (frame_size > 0)
6949 in->frames_read += bytes_read/frame_size;
6950
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006951 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306952 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006953 pthread_mutex_unlock(&in->lock);
6954
6955 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306956 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306957 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306958 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306959 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306960 in->standby = true;
6961 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306962 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05306963 bytes_read = bytes;
6964 memset(buffer, 0, bytes);
6965 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006966 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006967 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6968 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006969 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306970 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306971 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006972 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306973 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006974}
6975
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006976static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006977{
6978 return 0;
6979}
6980
Aalique Grahame22e49102018-12-18 14:23:57 -08006981static int in_get_capture_position(const struct audio_stream_in *stream,
6982 int64_t *frames, int64_t *time)
6983{
6984 if (stream == NULL || frames == NULL || time == NULL) {
6985 return -EINVAL;
6986 }
6987 struct stream_in *in = (struct stream_in *)stream;
6988 int ret = -ENOSYS;
6989
6990 lock_input_stream(in);
6991 // note: ST sessions do not close the alsa pcm driver synchronously
6992 // on standby. Therefore, we may return an error even though the
6993 // pcm stream is still opened.
6994 if (in->standby) {
6995 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6996 "%s stream in standby but pcm not NULL for non ST session", __func__);
6997 goto exit;
6998 }
6999 if (in->pcm) {
7000 struct timespec timestamp;
7001 unsigned int avail;
7002 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7003 *frames = in->frames_read + avail;
7004 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
7005 ret = 0;
7006 }
7007 }
7008exit:
7009 pthread_mutex_unlock(&in->lock);
7010 return ret;
7011}
7012
Carter Hsu2e429db2019-05-14 18:50:52 +08007013static int in_update_effect_list(bool add, effect_handle_t effect,
7014 struct listnode *head)
7015{
7016 struct listnode *node;
7017 struct in_effect_list *elist = NULL;
7018 struct in_effect_list *target = NULL;
7019 int ret = 0;
7020
7021 if (!head)
7022 return ret;
7023
7024 list_for_each(node, head) {
7025 elist = node_to_item(node, struct in_effect_list, list);
7026 if (elist->handle == effect) {
7027 target = elist;
7028 break;
7029 }
7030 }
7031
7032 if (add) {
7033 if (target) {
7034 ALOGD("effect %p already exist", effect);
7035 return ret;
7036 }
7037
7038 target = (struct in_effect_list *)
7039 calloc(1, sizeof(struct in_effect_list));
7040
7041 if (!target) {
7042 ALOGE("%s:fail to allocate memory", __func__);
7043 return -ENOMEM;
7044 }
7045
7046 target->handle = effect;
7047 list_add_tail(head, &target->list);
7048 } else {
7049 if (target) {
7050 list_remove(&target->list);
7051 free(target);
7052 }
7053 }
7054
7055 return ret;
7056}
7057
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007058static int add_remove_audio_effect(const struct audio_stream *stream,
7059 effect_handle_t effect,
7060 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007061{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007062 struct stream_in *in = (struct stream_in *)stream;
7063 int status = 0;
7064 effect_descriptor_t desc;
7065
7066 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007067 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7068
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007069 if (status != 0)
7070 return status;
7071
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007072 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007073 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007074 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007075 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7076 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007077 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007078
7079 in_update_effect_list(enable, effect, &in->aec_list);
7080 enable = !list_empty(&in->aec_list);
7081 if (enable == in->enable_aec)
7082 goto exit;
7083
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007084 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007085 ALOGD("AEC enable %d", enable);
7086
Aalique Grahame22e49102018-12-18 14:23:57 -08007087 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7088 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7089 in->dev->enable_voicerx = enable;
7090 struct audio_usecase *usecase;
7091 struct listnode *node;
7092 list_for_each(node, &in->dev->usecase_list) {
7093 usecase = node_to_item(node, struct audio_usecase, list);
7094 if (usecase->type == PCM_PLAYBACK)
7095 select_devices(in->dev, usecase->id);
7096 }
7097 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007098 if (!in->standby) {
7099 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7100 select_devices(in->dev, in->usecase);
7101 }
7102
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007103 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007104 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7105
7106 in_update_effect_list(enable, effect, &in->ns_list);
7107 enable = !list_empty(&in->ns_list);
7108 if (enable == in->enable_ns)
7109 goto exit;
7110
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007111 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007112 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007113 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007114 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7115 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007116 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7117 select_devices(in->dev, in->usecase);
7118 } else
7119 select_devices(in->dev, in->usecase);
7120 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007121 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007122exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007123 pthread_mutex_unlock(&in->dev->lock);
7124 pthread_mutex_unlock(&in->lock);
7125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007126 return 0;
7127}
7128
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007129static int in_add_audio_effect(const struct audio_stream *stream,
7130 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007131{
Eric Laurent994a6932013-07-17 11:51:42 -07007132 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007133 return add_remove_audio_effect(stream, effect, true);
7134}
7135
7136static int in_remove_audio_effect(const struct audio_stream *stream,
7137 effect_handle_t effect)
7138{
Eric Laurent994a6932013-07-17 11:51:42 -07007139 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007140 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007141}
7142
Derek Chenf939fb72018-11-13 13:34:41 -08007143streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7144 audio_io_handle_t input)
7145{
7146 struct listnode *node;
7147
7148 list_for_each(node, &dev->active_inputs_list) {
7149 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7150 streams_input_ctxt_t,
7151 list);
7152 if (in_ctxt->input->capture_handle == input) {
7153 return in_ctxt;
7154 }
7155 }
7156 return NULL;
7157}
7158
7159streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7160 audio_io_handle_t output)
7161{
7162 struct listnode *node;
7163
7164 list_for_each(node, &dev->active_outputs_list) {
7165 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7166 streams_output_ctxt_t,
7167 list);
7168 if (out_ctxt->output->handle == output) {
7169 return out_ctxt;
7170 }
7171 }
7172 return NULL;
7173}
7174
Haynes Mathew George16081042017-05-31 17:16:49 -07007175static int in_stop(const struct audio_stream_in* stream)
7176{
7177 struct stream_in *in = (struct stream_in *)stream;
7178 struct audio_device *adev = in->dev;
7179
7180 int ret = -ENOSYS;
7181 ALOGV("%s", __func__);
7182 pthread_mutex_lock(&adev->lock);
7183 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7184 in->capture_started && in->pcm != NULL) {
7185 pcm_stop(in->pcm);
7186 ret = stop_input_stream(in);
7187 in->capture_started = false;
7188 }
7189 pthread_mutex_unlock(&adev->lock);
7190 return ret;
7191}
7192
7193static int in_start(const struct audio_stream_in* stream)
7194{
7195 struct stream_in *in = (struct stream_in *)stream;
7196 struct audio_device *adev = in->dev;
7197 int ret = -ENOSYS;
7198
7199 ALOGV("%s in %p", __func__, in);
7200 pthread_mutex_lock(&adev->lock);
7201 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7202 !in->capture_started && in->pcm != NULL) {
7203 if (!in->capture_started) {
7204 ret = start_input_stream(in);
7205 if (ret == 0) {
7206 in->capture_started = true;
7207 }
7208 }
7209 }
7210 pthread_mutex_unlock(&adev->lock);
7211 return ret;
7212}
7213
Phil Burke0a86d12019-02-16 22:28:11 -08007214// Read offset for the positional timestamp from a persistent vendor property.
7215// This is to workaround apparent inaccuracies in the timing information that
7216// is used by the AAudio timing model. The inaccuracies can cause glitches.
7217static int64_t in_get_mmap_time_offset() {
7218 const int32_t kDefaultOffsetMicros = 0;
7219 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007220 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007221 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7222 return mmap_time_offset_micros * (int64_t)1000;
7223}
7224
Haynes Mathew George16081042017-05-31 17:16:49 -07007225static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7226 int32_t min_size_frames,
7227 struct audio_mmap_buffer_info *info)
7228{
7229 struct stream_in *in = (struct stream_in *)stream;
7230 struct audio_device *adev = in->dev;
7231 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007232 unsigned int offset1 = 0;
7233 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007234 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007235 uint32_t mmap_size = 0;
7236 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007237
7238 pthread_mutex_lock(&adev->lock);
7239 ALOGV("%s in %p", __func__, in);
7240
Sharad Sanglec6f32552018-05-04 16:15:38 +05307241 if (CARD_STATUS_OFFLINE == in->card_status||
7242 CARD_STATUS_OFFLINE == adev->card_status) {
7243 ALOGW("in->card_status or adev->card_status offline, try again");
7244 ret = -EIO;
7245 goto exit;
7246 }
7247
Haynes Mathew George16081042017-05-31 17:16:49 -07007248 if (info == NULL || min_size_frames == 0) {
7249 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7250 ret = -EINVAL;
7251 goto exit;
7252 }
7253 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7254 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7255 ALOGV("%s in %p", __func__, in);
7256 ret = -ENOSYS;
7257 goto exit;
7258 }
7259 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7260 if (in->pcm_device_id < 0) {
7261 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7262 __func__, in->pcm_device_id, in->usecase);
7263 ret = -EINVAL;
7264 goto exit;
7265 }
7266
7267 adjust_mmap_period_count(&in->config, min_size_frames);
7268
7269 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7270 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7271 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7272 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307273 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307274 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7275 in->card_status = CARD_STATUS_OFFLINE;
7276 adev->card_status = CARD_STATUS_OFFLINE;
7277 ret = -EIO;
7278 goto exit;
7279 }
7280
Haynes Mathew George16081042017-05-31 17:16:49 -07007281 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7282 step = "open";
7283 ret = -ENODEV;
7284 goto exit;
7285 }
7286
7287 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7288 if (ret < 0) {
7289 step = "begin";
7290 goto exit;
7291 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007292
Arun Mirpuri5d170872019-03-26 13:21:31 -07007293 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7294 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7295 info->burst_size_frames = in->config.period_size;
7296 ret = platform_get_mmap_data_fd(adev->platform,
7297 in->pcm_device_id, 1 /*capture*/,
7298 &info->shared_memory_fd,
7299 &mmap_size);
7300 if (ret < 0) {
7301 // Fall back to non exclusive mode
7302 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7303 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007304 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7305 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7306
Arun Mirpuri5d170872019-03-26 13:21:31 -07007307 if (mmap_size < buffer_size) {
7308 step = "mmap";
7309 goto exit;
7310 }
7311 // FIXME: indicate exclusive mode support by returning a negative buffer size
7312 info->buffer_size_frames *= -1;
7313 }
7314
7315 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007316
7317 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7318 if (ret < 0) {
7319 step = "commit";
7320 goto exit;
7321 }
7322
Phil Burke0a86d12019-02-16 22:28:11 -08007323 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7324
Haynes Mathew George16081042017-05-31 17:16:49 -07007325 in->standby = false;
7326 ret = 0;
7327
7328 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7329 __func__, info->shared_memory_address, info->buffer_size_frames);
7330
7331exit:
7332 if (ret != 0) {
7333 if (in->pcm == NULL) {
7334 ALOGE("%s: %s - %d", __func__, step, ret);
7335 } else {
7336 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7337 pcm_close(in->pcm);
7338 in->pcm = NULL;
7339 }
7340 }
7341 pthread_mutex_unlock(&adev->lock);
7342 return ret;
7343}
7344
7345static int in_get_mmap_position(const struct audio_stream_in *stream,
7346 struct audio_mmap_position *position)
7347{
7348 struct stream_in *in = (struct stream_in *)stream;
7349 ALOGVV("%s", __func__);
7350 if (position == NULL) {
7351 return -EINVAL;
7352 }
7353 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7354 return -ENOSYS;
7355 }
7356 if (in->pcm == NULL) {
7357 return -ENOSYS;
7358 }
7359 struct timespec ts = { 0, 0 };
7360 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7361 if (ret < 0) {
7362 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7363 return ret;
7364 }
Phil Burke0a86d12019-02-16 22:28:11 -08007365 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7366 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007367 return 0;
7368}
7369
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307370static int in_get_active_microphones(const struct audio_stream_in *stream,
7371 struct audio_microphone_characteristic_t *mic_array,
7372 size_t *mic_count) {
7373 struct stream_in *in = (struct stream_in *)stream;
7374 struct audio_device *adev = in->dev;
7375 ALOGVV("%s", __func__);
7376
7377 lock_input_stream(in);
7378 pthread_mutex_lock(&adev->lock);
7379 int ret = platform_get_active_microphones(adev->platform,
7380 audio_channel_count_from_in_mask(in->channel_mask),
7381 in->usecase, mic_array, mic_count);
7382 pthread_mutex_unlock(&adev->lock);
7383 pthread_mutex_unlock(&in->lock);
7384
7385 return ret;
7386}
7387
7388static int adev_get_microphones(const struct audio_hw_device *dev,
7389 struct audio_microphone_characteristic_t *mic_array,
7390 size_t *mic_count) {
7391 struct audio_device *adev = (struct audio_device *)dev;
7392 ALOGVV("%s", __func__);
7393
7394 pthread_mutex_lock(&adev->lock);
7395 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7396 pthread_mutex_unlock(&adev->lock);
7397
7398 return ret;
7399}
juyuchendb308c22019-01-21 11:57:17 -07007400
7401static void in_update_sink_metadata(struct audio_stream_in *stream,
7402 const struct sink_metadata *sink_metadata) {
7403
7404 if (stream == NULL
7405 || sink_metadata == NULL
7406 || sink_metadata->tracks == NULL) {
7407 return;
7408 }
7409
7410 int error = 0;
7411 struct stream_in *in = (struct stream_in *)stream;
7412 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007413 struct listnode devices;
7414
7415 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007416
7417 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007418 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007419
7420 lock_input_stream(in);
7421 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007422 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007423
7424 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007425 && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007426 && adev->voice_tx_output != NULL) {
7427 /* Use the rx device from afe-proxy record to route voice call because
7428 there is no routing if tx device is on primary hal and rx device
7429 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007430 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007431
7432 if (!voice_is_call_state_active(adev)) {
7433 if (adev->mode == AUDIO_MODE_IN_CALL) {
7434 adev->current_call_output = adev->voice_tx_output;
7435 error = voice_start_call(adev);
7436 if (error != 0)
7437 ALOGE("%s: start voice call failed %d", __func__, error);
7438 }
7439 } else {
7440 adev->current_call_output = adev->voice_tx_output;
7441 voice_update_devices_for_all_voice_usecases(adev);
7442 }
7443 }
7444
7445 pthread_mutex_unlock(&adev->lock);
7446 pthread_mutex_unlock(&in->lock);
7447}
7448
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307449int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007450 audio_io_handle_t handle,
7451 audio_devices_t devices,
7452 audio_output_flags_t flags,
7453 struct audio_config *config,
7454 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007455 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007456{
7457 struct audio_device *adev = (struct audio_device *)dev;
7458 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307459 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007460 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007461 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307462 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007463 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7464 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7465 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7466 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007467 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007468 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7469 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007470 bool force_haptic_path =
7471 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007472 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007473
kunleizdff872d2018-08-20 14:40:33 +08007474 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007475 is_usb_dev = false;
7476 devices = AUDIO_DEVICE_OUT_SPEAKER;
7477 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7478 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007479 if (config->format == AUDIO_FORMAT_DEFAULT)
7480 config->format = AUDIO_FORMAT_PCM_16_BIT;
7481 if (config->sample_rate == 0)
7482 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7483 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7484 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007485 }
7486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007487 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307488
Rahul Sharma99770982019-03-06 17:05:26 +05307489 pthread_mutex_lock(&adev->lock);
7490 if (out_get_stream(adev, handle) != NULL) {
7491 ALOGW("%s, output stream already opened", __func__);
7492 ret = -EEXIST;
7493 }
7494 pthread_mutex_unlock(&adev->lock);
7495 if (ret)
7496 return ret;
7497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007498 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7499
Mingming Yin3a941d42016-02-17 18:08:05 -08007500 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007501 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7502 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307503
7504
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007505 if (!out) {
7506 return -ENOMEM;
7507 }
7508
Haynes Mathew George204045b2015-02-25 20:32:03 -08007509 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007510 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307511 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007512 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007513 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007515 if (devices == AUDIO_DEVICE_NONE)
7516 devices = AUDIO_DEVICE_OUT_SPEAKER;
7517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007518 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007519 list_init(&out->device_list);
7520 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007521 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007522 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007523 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307524 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307525 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7526 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7527 else
7528 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007529 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007530 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007531 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307532 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307533 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307534 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007535 out->hal_output_suspend_supported = 0;
7536 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307537 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307538 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307539 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007540 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007541
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307542 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307543 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007544 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7545
Aalique Grahame22e49102018-12-18 14:23:57 -08007546 if (direct_dev &&
7547 (audio_is_linear_pcm(out->format) ||
7548 config->format == AUDIO_FORMAT_DEFAULT) &&
7549 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7550 audio_format_t req_format = config->format;
7551 audio_channel_mask_t req_channel_mask = config->channel_mask;
7552 uint32_t req_sample_rate = config->sample_rate;
7553
7554 pthread_mutex_lock(&adev->lock);
7555 if (is_hdmi) {
7556 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7557 ret = read_hdmi_sink_caps(out);
7558 if (config->sample_rate == 0)
7559 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7560 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7561 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7562 if (config->format == AUDIO_FORMAT_DEFAULT)
7563 config->format = AUDIO_FORMAT_PCM_16_BIT;
7564 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007565 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7566 &config->format,
7567 &out->supported_formats[0],
7568 MAX_SUPPORTED_FORMATS,
7569 &config->channel_mask,
7570 &out->supported_channel_masks[0],
7571 MAX_SUPPORTED_CHANNEL_MASKS,
7572 &config->sample_rate,
7573 &out->supported_sample_rates[0],
7574 MAX_SUPPORTED_SAMPLE_RATES);
7575 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007576 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007577
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007578 pthread_mutex_unlock(&adev->lock);
7579 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007580 if (ret == -ENOSYS) {
7581 /* ignore and go with default */
7582 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007583 }
7584 // For MMAP NO IRQ, allow conversions in ADSP
7585 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7586 goto error_open;
7587 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007588 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007589 goto error_open;
7590 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007591
7592 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7593 config->sample_rate = req_sample_rate;
7594 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7595 config->channel_mask = req_channel_mask;
7596 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7597 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007598 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007599
7600 out->sample_rate = config->sample_rate;
7601 out->channel_mask = config->channel_mask;
7602 out->format = config->format;
7603 if (is_hdmi) {
7604 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7605 out->config = pcm_config_hdmi_multi;
7606 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7607 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7608 out->config = pcm_config_mmap_playback;
7609 out->stream.start = out_start;
7610 out->stream.stop = out_stop;
7611 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7612 out->stream.get_mmap_position = out_get_mmap_position;
7613 } else {
7614 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7615 out->config = pcm_config_hifi;
7616 }
7617
7618 out->config.rate = out->sample_rate;
7619 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7620 if (is_hdmi) {
7621 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7622 audio_bytes_per_sample(out->format));
7623 }
7624 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007625 }
7626
Derek Chenf6318be2017-06-12 17:16:24 -04007627 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007628 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007629 /* extract car audio stream index */
7630 out->car_audio_stream =
7631 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7632 if (out->car_audio_stream < 0) {
7633 ALOGE("%s: invalid car audio stream %x",
7634 __func__, out->car_audio_stream);
7635 ret = -EINVAL;
7636 goto error_open;
7637 }
Derek Chen5f67a942020-02-24 23:08:13 -08007638 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007639 }
7640
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007641 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007642 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007643 if (!voice_extn_is_compress_voip_supported()) {
7644 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7645 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007646 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7647 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007648 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7649 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007650 out->volume_l = INVALID_OUT_VOLUME;
7651 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007652
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007653 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007654 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007655 uint32_t channel_count =
7656 audio_channel_count_from_out_mask(out->channel_mask);
7657 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7658 out->sample_rate, out->format,
7659 channel_count, false);
7660 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7661 if (frame_size != 0)
7662 out->config.period_size = buffer_size / frame_size;
7663 else
7664 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007665 }
7666 } else {
7667 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7668 voice_extn_compress_voip_is_active(out->dev)) &&
7669 (voice_extn_compress_voip_is_config_supported(config))) {
7670 ret = voice_extn_compress_voip_open_output_stream(out);
7671 if (ret != 0) {
7672 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7673 __func__, ret);
7674 goto error_open;
7675 }
Sujin Panicker19027262019-09-16 18:28:06 +05307676 } else {
7677 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7678 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007679 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007680 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007681 } else if (audio_is_linear_pcm(out->format) &&
7682 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7683 out->channel_mask = config->channel_mask;
7684 out->sample_rate = config->sample_rate;
7685 out->format = config->format;
7686 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7687 // does this change?
7688 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7689 out->config.rate = config->sample_rate;
7690 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7691 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7692 audio_bytes_per_sample(config->format));
7693 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007694 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307695 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307696 pthread_mutex_lock(&adev->lock);
7697 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7698 pthread_mutex_unlock(&adev->lock);
7699
7700 // reject offload during card offline to allow
7701 // fallback to s/w paths
7702 if (offline) {
7703 ret = -ENODEV;
7704 goto error_open;
7705 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007706
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007707 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7708 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7709 ALOGE("%s: Unsupported Offload information", __func__);
7710 ret = -EINVAL;
7711 goto error_open;
7712 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007713
Atul Khare3fa6e542017-08-09 00:56:17 +05307714 if (config->offload_info.format == 0)
7715 config->offload_info.format = config->format;
7716 if (config->offload_info.sample_rate == 0)
7717 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007718
Mingming Yin90310102013-11-13 16:57:00 -08007719 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307720 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007721 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007722 ret = -EINVAL;
7723 goto error_open;
7724 }
7725
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007726 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7727 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7728 (audio_extn_passthru_is_passthrough_stream(out)) &&
7729 !((config->sample_rate == 48000) ||
7730 (config->sample_rate == 96000) ||
7731 (config->sample_rate == 192000))) {
7732 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7733 __func__, config->sample_rate, config->offload_info.format);
7734 ret = -EINVAL;
7735 goto error_open;
7736 }
7737
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007738 out->compr_config.codec = (struct snd_codec *)
7739 calloc(1, sizeof(struct snd_codec));
7740
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007741 if (!out->compr_config.codec) {
7742 ret = -ENOMEM;
7743 goto error_open;
7744 }
7745
Dhananjay Kumarac341582017-02-23 23:42:25 +05307746 out->stream.pause = out_pause;
7747 out->stream.resume = out_resume;
7748 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307749 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307750 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007751 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307752 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007753 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307754 } else {
7755 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7756 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007757 }
vivek mehta446c3962015-09-14 10:57:35 -07007758
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307759 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7760 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007761#ifdef AUDIO_GKI_ENABLED
7762 /* out->compr_config.codec->reserved[1] is for flags */
7763 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7764#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307765 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007766#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307767 }
7768
vivek mehta446c3962015-09-14 10:57:35 -07007769 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007770 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007771 config->format == 0 && config->sample_rate == 0 &&
7772 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007773 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007774 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7775 } else {
7776 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7777 ret = -EEXIST;
7778 goto error_open;
7779 }
vivek mehta446c3962015-09-14 10:57:35 -07007780 }
7781
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007782 if (config->offload_info.channel_mask)
7783 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007784 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007785 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007786 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007787 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307788 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007789 ret = -EINVAL;
7790 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007791 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007792
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007793 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007794 out->sample_rate = config->offload_info.sample_rate;
7795
Mingming Yin3ee55c62014-08-04 14:23:35 -07007796 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007797
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307798 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307799 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307800 audio_extn_dolby_send_ddp_endp_params(adev);
7801 audio_extn_dolby_set_dmid(adev);
7802 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007803
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007804 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007805 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007806 out->compr_config.codec->bit_rate =
7807 config->offload_info.bit_rate;
7808 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307809 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007810 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307811 /* Update bit width only for non passthrough usecases.
7812 * For passthrough usecases, the output will always be opened @16 bit
7813 */
7814 if (!audio_extn_passthru_is_passthrough_stream(out))
7815 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307816
7817 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007818#ifdef AUDIO_GKI_ENABLED
7819 /* out->compr_config.codec->reserved[1] is for flags */
7820 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7821 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7822#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307823 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7824 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007825#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307826
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007827 /*TODO: Do we need to change it for passthrough */
7828 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007829
Manish Dewangana6fc5442015-08-24 20:30:31 +05307830 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7831 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307832 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307833 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307834 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7835 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307836
7837 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7838 AUDIO_FORMAT_PCM) {
7839
7840 /*Based on platform support, configure appropriate alsa format for corresponding
7841 *hal input format.
7842 */
7843 out->compr_config.codec->format = hal_format_to_alsa(
7844 config->offload_info.format);
7845
Ashish Jain83a6cc22016-06-28 14:34:17 +05307846 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307847 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307848 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307849
Dhananjay Kumarac341582017-02-23 23:42:25 +05307850 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307851 *hal input format and alsa format might differ based on platform support.
7852 */
7853 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307854 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307855
7856 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7857
Deeraj Soman93155a62019-09-30 19:00:37 +05307858 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7859 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7860 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7861 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7862 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307863
Ashish Jainf1eaa582016-05-23 20:54:24 +05307864 /* Check if alsa session is configured with the same format as HAL input format,
7865 * if not then derive correct fragment size needed to accomodate the
7866 * conversion of HAL input format to alsa format.
7867 */
7868 audio_extn_utils_update_direct_pcm_fragment_size(out);
7869
7870 /*if hal input and output fragment size is different this indicates HAL input format is
7871 *not same as the alsa format
7872 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307873 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307874 /*Allocate a buffer to convert input data to the alsa configured format.
7875 *size of convert buffer is equal to the size required to hold one fragment size
7876 *worth of pcm data, this is because flinger does not write more than fragment_size
7877 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307878 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7879 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307880 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7881 ret = -ENOMEM;
7882 goto error_open;
7883 }
7884 }
7885 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7886 out->compr_config.fragment_size =
7887 audio_extn_passthru_get_buffer_size(&config->offload_info);
7888 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7889 } else {
7890 out->compr_config.fragment_size =
7891 platform_get_compress_offload_buffer_size(&config->offload_info);
7892 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7893 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007894
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307895 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7896 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7897 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007898 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307899 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007900
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307901 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7902 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7903 }
7904
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007905 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7906 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007907
Manish Dewangan69426c82017-01-30 17:35:36 +05307908 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7909 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7910 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7911 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7912 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7913 } else {
7914 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7915 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007916
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307917 memset(&out->channel_map_param, 0,
7918 sizeof(struct audio_out_channel_map_param));
7919
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007920 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307921 out->send_next_track_params = false;
7922 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007923 out->offload_state = OFFLOAD_STATE_IDLE;
7924 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007925 out->writeAt.tv_sec = 0;
7926 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007927
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007928 audio_extn_dts_create_state_notifier_node(out->usecase);
7929
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007930 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7931 __func__, config->offload_info.version,
7932 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307933
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307934 /* Check if DSD audio format is supported in codec
7935 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307936 */
7937
7938 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307939 (!platform_check_codec_dsd_support(adev->platform) ||
7940 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307941 ret = -EINVAL;
7942 goto error_open;
7943 }
7944
Ashish Jain5106d362016-05-11 19:23:33 +05307945 /* Disable gapless if any of the following is true
7946 * passthrough playback
7947 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307948 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307949 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307950 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307951 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007952 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307953 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307954 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307955 check_and_set_gapless_mode(adev, false);
7956 } else
7957 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007958
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307959 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007960 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7961 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307962 if (config->format == AUDIO_FORMAT_DSD) {
7963 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08007964#ifdef AUDIO_GKI_ENABLED
7965 /* out->compr_config.codec->reserved[0] is for compr_passthr */
7966 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
7967#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307968 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08007969#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307970 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007971
7972 create_offload_callback_thread(out);
7973
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007974 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007975 switch (config->sample_rate) {
7976 case 0:
7977 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7978 break;
7979 case 8000:
7980 case 16000:
7981 case 48000:
7982 out->sample_rate = config->sample_rate;
7983 break;
7984 default:
7985 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7986 config->sample_rate);
7987 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7988 ret = -EINVAL;
7989 goto error_open;
7990 }
7991 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7992 switch (config->channel_mask) {
7993 case AUDIO_CHANNEL_NONE:
7994 case AUDIO_CHANNEL_OUT_STEREO:
7995 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7996 break;
7997 default:
7998 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7999 config->channel_mask);
8000 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8001 ret = -EINVAL;
8002 goto error_open;
8003 }
8004 switch (config->format) {
8005 case AUDIO_FORMAT_DEFAULT:
8006 case AUDIO_FORMAT_PCM_16_BIT:
8007 out->format = AUDIO_FORMAT_PCM_16_BIT;
8008 break;
8009 default:
8010 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8011 config->format);
8012 config->format = AUDIO_FORMAT_PCM_16_BIT;
8013 ret = -EINVAL;
8014 goto error_open;
8015 }
8016
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308017 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008018 if (ret != 0) {
8019 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008020 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008021 goto error_open;
8022 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008023 } else if (is_single_device_type_equal(&out->device_list,
8024 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008025 switch (config->sample_rate) {
8026 case 0:
8027 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8028 break;
8029 case 8000:
8030 case 16000:
8031 case 48000:
8032 out->sample_rate = config->sample_rate;
8033 break;
8034 default:
8035 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8036 config->sample_rate);
8037 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8038 ret = -EINVAL;
8039 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008040 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008041 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8042 switch (config->channel_mask) {
8043 case AUDIO_CHANNEL_NONE:
8044 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8045 break;
8046 case AUDIO_CHANNEL_OUT_STEREO:
8047 out->channel_mask = config->channel_mask;
8048 break;
8049 default:
8050 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8051 config->channel_mask);
8052 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8053 ret = -EINVAL;
8054 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008055 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008056 switch (config->format) {
8057 case AUDIO_FORMAT_DEFAULT:
8058 out->format = AUDIO_FORMAT_PCM_16_BIT;
8059 break;
8060 case AUDIO_FORMAT_PCM_16_BIT:
8061 out->format = config->format;
8062 break;
8063 default:
8064 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8065 config->format);
8066 config->format = AUDIO_FORMAT_PCM_16_BIT;
8067 ret = -EINVAL;
8068 break;
8069 }
8070 if (ret != 0)
8071 goto error_open;
8072
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008073 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8074 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008075 out->config.rate = out->sample_rate;
8076 out->config.channels =
8077 audio_channel_count_from_out_mask(out->channel_mask);
8078 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008079 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008080 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308081 unsigned int channels = 0;
8082 /*Update config params to default if not set by the caller*/
8083 if (config->sample_rate == 0)
8084 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8085 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8086 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8087 if (config->format == AUDIO_FORMAT_DEFAULT)
8088 config->format = AUDIO_FORMAT_PCM_16_BIT;
8089
8090 channels = audio_channel_count_from_out_mask(out->channel_mask);
8091
Varun Balaraje49253e2017-07-06 19:48:56 +05308092 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8093 out->usecase = get_interactive_usecase(adev);
8094 out->config = pcm_config_low_latency;
8095 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308096 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008097 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8098 out->flags);
8099 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008100 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8101 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8102 out->config = pcm_config_mmap_playback;
8103 out->stream.start = out_start;
8104 out->stream.stop = out_stop;
8105 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8106 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308107 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8108 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008109 out->hal_output_suspend_supported =
8110 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8111 out->dynamic_pm_qos_config_supported =
8112 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8113 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008114 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8115 } else {
8116 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8117 //the mixer path will be a string similar to "low-latency-playback resume"
8118 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8119 strlcat(out->pm_qos_mixer_path,
8120 " resume", MAX_MIXER_PATH_LEN);
8121 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8122 out->pm_qos_mixer_path);
8123 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308124 out->config = pcm_config_low_latency;
8125 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8126 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8127 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308128 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8129 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8130 if (out->config.period_size <= 0) {
8131 ALOGE("Invalid configuration period size is not valid");
8132 ret = -EINVAL;
8133 goto error_open;
8134 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008135 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8136 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8137 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008138 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8139 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8140 out->config = pcm_config_haptics_audio;
8141 if (force_haptic_path)
8142 adev->haptics_config = pcm_config_haptics_audio;
8143 else
8144 adev->haptics_config = pcm_config_haptics;
8145
Meng Wangd08ce322020-04-02 08:59:20 +08008146 channels =
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008147 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8148
8149 if (force_haptic_path) {
8150 out->config.channels = 1;
8151 adev->haptics_config.channels = 1;
8152 } else
8153 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 -08008154 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008155 ret = audio_extn_auto_hal_open_output_stream(out);
8156 if (ret) {
8157 ALOGE("%s: Failed to open output stream for bus device", __func__);
8158 ret = -EINVAL;
8159 goto error_open;
8160 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308161 } else {
8162 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008163 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8164 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308165 }
8166 out->hal_ip_format = format = out->format;
8167 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8168 out->hal_op_format = pcm_format_to_hal(out->config.format);
8169 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8170 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008171 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308172 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308173 if (out->hal_ip_format != out->hal_op_format) {
8174 uint32_t buffer_size = out->config.period_size *
8175 format_to_bitwidth_table[out->hal_op_format] *
8176 out->config.channels;
8177 out->convert_buffer = calloc(1, buffer_size);
8178 if (out->convert_buffer == NULL){
8179 ALOGE("Allocation failed for convert buffer for size %d",
8180 out->compr_config.fragment_size);
8181 ret = -ENOMEM;
8182 goto error_open;
8183 }
8184 ALOGD("Convert buffer allocated of size %d", buffer_size);
8185 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008186 }
8187
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008188 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8189 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308190
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008191 /* TODO remove this hardcoding and check why width is zero*/
8192 if (out->bit_width == 0)
8193 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308194 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008195 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008196 &out->device_list, out->flags,
8197 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308198 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308199 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008200 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008201 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8202 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008203 if(adev->primary_output == NULL)
8204 adev->primary_output = out;
8205 else {
8206 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008207 ret = -EEXIST;
8208 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008209 }
8210 }
8211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008212 /* Check if this usecase is already existing */
8213 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008214 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8215 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008216 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008217 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008218 ret = -EEXIST;
8219 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008220 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008222 pthread_mutex_unlock(&adev->lock);
8223
8224 out->stream.common.get_sample_rate = out_get_sample_rate;
8225 out->stream.common.set_sample_rate = out_set_sample_rate;
8226 out->stream.common.get_buffer_size = out_get_buffer_size;
8227 out->stream.common.get_channels = out_get_channels;
8228 out->stream.common.get_format = out_get_format;
8229 out->stream.common.set_format = out_set_format;
8230 out->stream.common.standby = out_standby;
8231 out->stream.common.dump = out_dump;
8232 out->stream.common.set_parameters = out_set_parameters;
8233 out->stream.common.get_parameters = out_get_parameters;
8234 out->stream.common.add_audio_effect = out_add_audio_effect;
8235 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8236 out->stream.get_latency = out_get_latency;
8237 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008238#ifdef NO_AUDIO_OUT
8239 out->stream.write = out_write_for_no_output;
8240#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008241 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008242#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008243 out->stream.get_render_position = out_get_render_position;
8244 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008245 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008246
Haynes Mathew George16081042017-05-31 17:16:49 -07008247 if (out->realtime)
8248 out->af_period_multiplier = af_period_multiplier;
8249 else
8250 out->af_period_multiplier = 1;
8251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008252 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008253 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008254 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008255
8256 config->format = out->stream.common.get_format(&out->stream.common);
8257 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8258 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308259 register_format(out->format, out->supported_formats);
8260 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8261 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008262
Aalique Grahame22e49102018-12-18 14:23:57 -08008263 out->error_log = error_log_create(
8264 ERROR_LOG_ENTRIES,
8265 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8266
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308267 /*
8268 By locking output stream before registering, we allow the callback
8269 to update stream's state only after stream's initial state is set to
8270 adev state.
8271 */
8272 lock_output_stream(out);
8273 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8274 pthread_mutex_lock(&adev->lock);
8275 out->card_status = adev->card_status;
8276 pthread_mutex_unlock(&adev->lock);
8277 pthread_mutex_unlock(&out->lock);
8278
Aalique Grahame22e49102018-12-18 14:23:57 -08008279 stream_app_type_cfg_init(&out->app_type_cfg);
8280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008281 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308282 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008283 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008284
8285 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8286 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8287 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008288 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308289 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008290 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008291 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308292 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8293 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008294 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8295 out->usecase, PCM_PLAYBACK);
8296 hdlr_stream_cfg.flags = out->flags;
8297 hdlr_stream_cfg.type = PCM_PLAYBACK;
8298 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8299 &hdlr_stream_cfg);
8300 if (ret) {
8301 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8302 out->adsp_hdlr_stream_handle = NULL;
8303 }
8304 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308305 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8306 is_direct_passthough, false);
8307 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8308 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008309 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008310 if (ret < 0) {
8311 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8312 out->ip_hdlr_handle = NULL;
8313 }
8314 }
Derek Chenf939fb72018-11-13 13:34:41 -08008315
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008316 ret = io_streams_map_insert(adev, &out->stream.common,
8317 out->handle, AUDIO_PATCH_HANDLE_NONE);
8318 if (ret != 0)
8319 goto error_open;
8320
Derek Chenf939fb72018-11-13 13:34:41 -08008321 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8322 calloc(1, sizeof(streams_output_ctxt_t));
8323 if (out_ctxt == NULL) {
8324 ALOGE("%s fail to allocate output ctxt", __func__);
8325 ret = -ENOMEM;
8326 goto error_open;
8327 }
8328 out_ctxt->output = out;
8329
8330 pthread_mutex_lock(&adev->lock);
8331 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8332 pthread_mutex_unlock(&adev->lock);
8333
Eric Laurent994a6932013-07-17 11:51:42 -07008334 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008335 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008336
8337error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308338 if (out->convert_buffer)
8339 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008340 free(out);
8341 *stream_out = NULL;
8342 ALOGD("%s: exit: ret %d", __func__, ret);
8343 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008344}
8345
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308346void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008347 struct audio_stream_out *stream)
8348{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008349 struct stream_out *out = (struct stream_out *)stream;
8350 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008351 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008352
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008353 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308354
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008355 io_streams_map_remove(adev, out->handle);
8356
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308357 // must deregister from sndmonitor first to prevent races
8358 // between the callback and close_stream
8359 audio_extn_snd_mon_unregister_listener(out);
8360
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008361 /* close adsp hdrl session before standby */
8362 if (out->adsp_hdlr_stream_handle) {
8363 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8364 if (ret)
8365 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8366 out->adsp_hdlr_stream_handle = NULL;
8367 }
8368
Manish Dewangan21a850a2017-08-14 12:03:55 +05308369 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008370 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8371 out->ip_hdlr_handle = NULL;
8372 }
8373
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008374 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308375 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008376 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308377 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308378 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008379 if(ret != 0)
8380 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8381 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008382 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008383 out_standby(&stream->common);
8384
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008385 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008386 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008387 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008388 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008389 if (out->compr_config.codec != NULL)
8390 free(out->compr_config.codec);
8391 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008392
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308393 out->a2dp_compress_mute = false;
8394
Varun Balaraje49253e2017-07-06 19:48:56 +05308395 if (is_interactive_usecase(out->usecase))
8396 free_interactive_usecase(adev, out->usecase);
8397
Ashish Jain83a6cc22016-06-28 14:34:17 +05308398 if (out->convert_buffer != NULL) {
8399 free(out->convert_buffer);
8400 out->convert_buffer = NULL;
8401 }
8402
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008403 if (adev->voice_tx_output == out)
8404 adev->voice_tx_output = NULL;
8405
Aalique Grahame22e49102018-12-18 14:23:57 -08008406 error_log_destroy(out->error_log);
8407 out->error_log = NULL;
8408
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308409 if (adev->primary_output == out)
8410 adev->primary_output = NULL;
8411
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008412 pthread_cond_destroy(&out->cond);
8413 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008414
8415 pthread_mutex_lock(&adev->lock);
8416 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8417 if (out_ctxt != NULL) {
8418 list_remove(&out_ctxt->list);
8419 free(out_ctxt);
8420 } else {
8421 ALOGW("%s, output stream already closed", __func__);
8422 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008423 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008424 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008425 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008426}
8427
8428static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8429{
8430 struct audio_device *adev = (struct audio_device *)dev;
8431 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008432 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008433 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008434 int ret;
8435 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008436 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008437 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008438 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008439
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008440 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008441 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008442
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308443 if (!parms)
8444 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308445
Derek Chen6f293672019-04-01 01:40:24 -07008446 /* notify adev and input/output streams on the snd card status */
8447 adev_snd_mon_cb((void *)adev, parms);
8448
8449 list_for_each(node, &adev->active_outputs_list) {
8450 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8451 streams_output_ctxt_t,
8452 list);
8453 out_snd_mon_cb((void *)out_ctxt->output, parms);
8454 }
8455
8456 list_for_each(node, &adev->active_inputs_list) {
8457 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8458 streams_input_ctxt_t,
8459 list);
8460 in_snd_mon_cb((void *)in_ctxt->input, parms);
8461 }
8462
Zhou Songd6d71752019-05-21 18:08:51 +08008463 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308464 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8465 if (ret >= 0) {
8466 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008467 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308468 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008469 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308470 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008471 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008472 }
8473 }
8474
8475 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8476 if (ret>=0) {
8477 if (!strncmp(value, "false", 5) &&
8478 audio_extn_a2dp_source_is_suspended()) {
8479 struct audio_usecase *usecase;
8480 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008481 list_for_each(node, &adev->usecase_list) {
8482 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008483 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008484 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008485 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008486 reassign_device_list(&usecase->stream.in->device_list,
8487 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008488 select_devices(adev, usecase->id);
8489 }
Zhou Songd6d71752019-05-21 18:08:51 +08008490 }
8491 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308492 }
8493
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008494 status = voice_set_parameters(adev, parms);
8495 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008496 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008497
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008498 status = platform_set_parameters(adev->platform, parms);
8499 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008500 goto done;
8501
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008502 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8503 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008504 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008505 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8506 adev->bluetooth_nrec = true;
8507 else
8508 adev->bluetooth_nrec = false;
8509 }
8510
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008511 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8512 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008513 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8514 adev->screen_off = false;
8515 else
8516 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008517 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008518 }
8519
Eric Laurent4b084132018-10-19 17:33:43 -07008520 ret = str_parms_get_int(parms, "rotation", &val);
8521 if (ret >= 0) {
8522 bool reverse_speakers = false;
8523 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8524 switch (val) {
8525 // FIXME: note that the code below assumes that the speakers are in the correct placement
8526 // relative to the user when the device is rotated 90deg from its default rotation. This
8527 // assumption is device-specific, not platform-specific like this code.
8528 case 270:
8529 reverse_speakers = true;
8530 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8531 break;
8532 case 0:
8533 case 180:
8534 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8535 break;
8536 case 90:
8537 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8538 break;
8539 default:
8540 ALOGE("%s: unexpected rotation of %d", __func__, val);
8541 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008542 }
Eric Laurent4b084132018-10-19 17:33:43 -07008543 if (status == 0) {
8544 // check and set swap
8545 // - check if orientation changed and speaker active
8546 // - set rotation and cache the rotation value
8547 adev->camera_orientation =
8548 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8549 if (!audio_extn_is_maxx_audio_enabled())
8550 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8551 }
8552 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008553
Mingming Yin514a8bc2014-07-29 15:22:21 -07008554 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8555 if (ret >= 0) {
8556 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8557 adev->bt_wb_speech_enabled = true;
8558 else
8559 adev->bt_wb_speech_enabled = false;
8560 }
8561
Zhou Song12c29502019-03-16 10:37:18 +08008562 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8563 if (ret >= 0) {
8564 val = atoi(value);
8565 adev->swb_speech_mode = val;
8566 }
8567
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008568 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8569 if (ret >= 0) {
8570 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308571 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008572 if (audio_is_output_device(val) &&
8573 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008574 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008575 platform_get_controller_stream_from_params(parms, &controller, &stream);
8576 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8577 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008578 if (ret < 0) {
8579 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308580 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008581 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008582 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308583 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008584 /*
8585 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8586 * Per AudioPolicyManager, USB device is higher priority than WFD.
8587 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8588 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8589 * starting voice call on USB
8590 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008591 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308592 if (ret >= 0)
8593 audio_extn_usb_add_device(device, atoi(value));
8594
Zhou Song6f862822017-11-06 17:27:57 +08008595 if (!audio_extn_usb_is_tunnel_supported()) {
8596 ALOGV("detected USB connect .. disable proxy");
8597 adev->allow_afe_proxy_usage = false;
8598 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008599 }
8600 }
8601
8602 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8603 if (ret >= 0) {
8604 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308605 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008606 /*
8607 * The HDMI / Displayport disconnect handling has been moved to
8608 * audio extension to ensure that its parameters are not
8609 * invalidated prior to updating sysfs of the disconnect event
8610 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8611 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308612 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008613 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308614 if (ret >= 0)
8615 audio_extn_usb_remove_device(device, atoi(value));
8616
Zhou Song6f862822017-11-06 17:27:57 +08008617 if (!audio_extn_usb_is_tunnel_supported()) {
8618 ALOGV("detected USB disconnect .. enable proxy");
8619 adev->allow_afe_proxy_usage = true;
8620 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008621 }
8622 }
8623
Aalique Grahame22e49102018-12-18 14:23:57 -08008624 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008625 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008626
8627 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008628 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308629 struct audio_usecase *usecase;
8630 struct listnode *node;
8631 list_for_each(node, &adev->usecase_list) {
8632 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308633 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008634 is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308635 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008636 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308637 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008638 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308639 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308640 ALOGD("Switching to speaker and muting the stream before select_devices");
8641 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308642 //force device switch to re configure encoder
8643 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308644 ALOGD("Unmuting the stream after select_devices");
8645 usecase->stream.out->a2dp_compress_mute = false;
8646 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 +05308647 audio_extn_a2dp_set_handoff_mode(false);
8648 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308649 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308650 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8651 usecase->stream.out->a2dp_compress_mute) {
8652 pthread_mutex_unlock(&adev->lock);
8653 lock_output_stream(usecase->stream.out);
8654 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008655 reassign_device_list(&usecase->stream.out->device_list,
8656 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308657 check_a2dp_restore_l(adev, usecase->stream.out, true);
8658 pthread_mutex_unlock(&usecase->stream.out->lock);
8659 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308660 }
8661 }
8662 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008663
8664 //handle vr audio setparam
8665 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8666 value, sizeof(value));
8667 if (ret >= 0) {
8668 ALOGI("Setting vr mode to be %s", value);
8669 if (!strncmp(value, "true", 4)) {
8670 adev->vr_audio_mode_enabled = true;
8671 ALOGI("Setting vr mode to true");
8672 } else if (!strncmp(value, "false", 5)) {
8673 adev->vr_audio_mode_enabled = false;
8674 ALOGI("Setting vr mode to false");
8675 } else {
8676 ALOGI("wrong vr mode set");
8677 }
8678 }
8679
Eric Laurent4b084132018-10-19 17:33:43 -07008680 //FIXME: to be replaced by proper video capture properties API
8681 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8682 if (ret >= 0) {
8683 int camera_facing = CAMERA_FACING_BACK;
8684 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8685 camera_facing = CAMERA_FACING_FRONT;
8686 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8687 camera_facing = CAMERA_FACING_BACK;
8688 else {
8689 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8690 goto done;
8691 }
8692 adev->camera_orientation =
8693 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8694 struct audio_usecase *usecase;
8695 struct listnode *node;
8696 list_for_each(node, &adev->usecase_list) {
8697 usecase = node_to_item(node, struct audio_usecase, list);
8698 struct stream_in *in = usecase->stream.in;
8699 if (usecase->type == PCM_CAPTURE && in != NULL &&
8700 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8701 select_devices(adev, in->usecase);
8702 }
8703 }
8704 }
8705
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308706 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008707done:
8708 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008709 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308710error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008711 ALOGV("%s: exit with code(%d)", __func__, status);
8712 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008713}
8714
8715static char* adev_get_parameters(const struct audio_hw_device *dev,
8716 const char *keys)
8717{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308718 ALOGD("%s:%s", __func__, keys);
8719
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008720 struct audio_device *adev = (struct audio_device *)dev;
8721 struct str_parms *reply = str_parms_create();
8722 struct str_parms *query = str_parms_create_str(keys);
8723 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308724 char value[256] = {0};
8725 int ret = 0;
8726
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008727 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008728 if (reply) {
8729 str_parms_destroy(reply);
8730 }
8731 if (query) {
8732 str_parms_destroy(query);
8733 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008734 ALOGE("adev_get_parameters: failed to create query or reply");
8735 return NULL;
8736 }
8737
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008738 //handle vr audio getparam
8739
8740 ret = str_parms_get_str(query,
8741 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8742 value, sizeof(value));
8743
8744 if (ret >= 0) {
8745 bool vr_audio_enabled = false;
8746 pthread_mutex_lock(&adev->lock);
8747 vr_audio_enabled = adev->vr_audio_mode_enabled;
8748 pthread_mutex_unlock(&adev->lock);
8749
8750 ALOGI("getting vr mode to %d", vr_audio_enabled);
8751
8752 if (vr_audio_enabled) {
8753 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8754 "true");
8755 goto exit;
8756 } else {
8757 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8758 "false");
8759 goto exit;
8760 }
8761 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008762
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008763 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008764 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008765 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008766 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008767 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308768 pthread_mutex_unlock(&adev->lock);
8769
Naresh Tannirud7205b62014-06-20 02:54:48 +05308770exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008771 str = str_parms_to_str(reply);
8772 str_parms_destroy(query);
8773 str_parms_destroy(reply);
8774
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308775 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008776 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008777}
8778
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008779static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008780{
8781 return 0;
8782}
8783
8784static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8785{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008786 int ret;
8787 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008788
8789 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8790
Haynes Mathew George5191a852013-09-11 14:19:36 -07008791 pthread_mutex_lock(&adev->lock);
8792 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008793 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008794 pthread_mutex_unlock(&adev->lock);
8795 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008796}
8797
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008798static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8799 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008800{
8801 return -ENOSYS;
8802}
8803
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008804static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8805 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008806{
8807 return -ENOSYS;
8808}
8809
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008810static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8811 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008812{
8813 return -ENOSYS;
8814}
8815
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008816static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8817 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008818{
8819 return -ENOSYS;
8820}
8821
8822static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8823{
8824 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008825 struct listnode *node;
8826 struct audio_usecase *usecase = NULL;
8827 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008828
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008829 pthread_mutex_lock(&adev->lock);
8830 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05308831 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
8832 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008833 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05308834 if( mode == AUDIO_MODE_CALL_SCREEN ){
8835 adev->current_call_output = adev->primary_output;
8836 voice_start_call(adev);
8837 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008838 (mode == AUDIO_MODE_NORMAL ||
8839 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008840 list_for_each(node, &adev->usecase_list) {
8841 usecase = node_to_item(node, struct audio_usecase, list);
8842 if (usecase->type == VOICE_CALL)
8843 break;
8844 }
8845 if (usecase &&
8846 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8847 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8848 true);
8849 if (ret != 0) {
8850 /* default service interval was successfully updated,
8851 reopen USB backend with new service interval */
8852 check_usecases_codec_backend(adev,
8853 usecase,
8854 usecase->out_snd_device);
8855 }
8856 }
8857
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008858 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008859 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008860 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008861 // restore device for other active usecases after stop call
8862 list_for_each(node, &adev->usecase_list) {
8863 usecase = node_to_item(node, struct audio_usecase, list);
8864 select_devices(adev, usecase->id);
8865 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008866 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008867 }
8868 pthread_mutex_unlock(&adev->lock);
8869 return 0;
8870}
8871
8872static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8873{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008874 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008875 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008876
8877 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008878 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008879 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008880
Derek Chend2530072014-11-24 12:39:14 -08008881 if (adev->ext_hw_plugin)
8882 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008883
8884 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008885 pthread_mutex_unlock(&adev->lock);
8886
8887 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008888}
8889
8890static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8891{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008892 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008893 return 0;
8894}
8895
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008896static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008897 const struct audio_config *config)
8898{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008899 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008900
Aalique Grahame22e49102018-12-18 14:23:57 -08008901 /* Don't know if USB HIFI in this context so use true to be conservative */
8902 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8903 true /*is_usb_hifi */) != 0)
8904 return 0;
8905
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008906 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8907 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008908}
8909
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008910static bool adev_input_allow_hifi_record(struct audio_device *adev,
8911 audio_devices_t devices,
8912 audio_input_flags_t flags,
8913 audio_source_t source) {
8914 const bool allowed = true;
8915
8916 if (!audio_is_usb_in_device(devices))
8917 return !allowed;
8918
8919 switch (flags) {
8920 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008921 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008922 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8923 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008924 default:
8925 return !allowed;
8926 }
8927
8928 switch (source) {
8929 case AUDIO_SOURCE_DEFAULT:
8930 case AUDIO_SOURCE_MIC:
8931 case AUDIO_SOURCE_UNPROCESSED:
8932 break;
8933 default:
8934 return !allowed;
8935 }
8936
8937 switch (adev->mode) {
8938 case 0:
8939 break;
8940 default:
8941 return !allowed;
8942 }
8943
8944 return allowed;
8945}
8946
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008947static int adev_update_voice_comm_input_stream(struct stream_in *in,
8948 struct audio_config *config)
8949{
8950 bool valid_rate = (config->sample_rate == 8000 ||
8951 config->sample_rate == 16000 ||
8952 config->sample_rate == 32000 ||
8953 config->sample_rate == 48000);
8954 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8955
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008956 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008957 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008958 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8959 in->config = default_pcm_config_voip_copp;
8960 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8961 DEFAULT_VOIP_BUF_DURATION_MS,
8962 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008963 } else {
8964 ALOGW("%s No valid input in voip, use defaults"
8965 "sample rate %u, channel mask 0x%X",
8966 __func__, config->sample_rate, in->channel_mask);
8967 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008968 in->config.rate = config->sample_rate;
8969 in->sample_rate = config->sample_rate;
8970 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008971 //XXX needed for voice_extn_compress_voip_open_input_stream
8972 in->config.rate = config->sample_rate;
8973 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05308974 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008975 voice_extn_compress_voip_is_active(in->dev)) &&
8976 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8977 valid_rate && valid_ch) {
8978 voice_extn_compress_voip_open_input_stream(in);
8979 // update rate entries to match config from AF
8980 in->config.rate = config->sample_rate;
8981 in->sample_rate = config->sample_rate;
8982 } else {
8983 ALOGW("%s compress voip not active, use defaults", __func__);
8984 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008985 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008986 return 0;
8987}
8988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008989static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008990 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008991 audio_devices_t devices,
8992 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008993 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308994 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008995 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008996 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008997{
8998 struct audio_device *adev = (struct audio_device *)dev;
8999 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009000 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009001 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009002 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309003 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009004 bool is_usb_dev = audio_is_usb_in_device(devices);
9005 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9006 devices,
9007 flags,
9008 source);
Andy Hung94320602018-10-29 18:31:12 -07009009 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9010 " sample_rate %u, channel_mask %#x, format %#x",
9011 __func__, flags, is_usb_dev, may_use_hifi_record,
9012 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309013
kunleizdff872d2018-08-20 14:40:33 +08009014 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009015 is_usb_dev = false;
9016 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9017 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9018 __func__, devices);
9019 }
9020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009021 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009022
9023 if (!(is_usb_dev && may_use_hifi_record)) {
9024 if (config->sample_rate == 0)
9025 config->sample_rate = 48000;
9026 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9027 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9028 if (config->format == AUDIO_FORMAT_DEFAULT)
9029 config->format = AUDIO_FORMAT_PCM_16_BIT;
9030
9031 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9032
Aalique Grahame22e49102018-12-18 14:23:57 -08009033 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9034 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009035 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309036 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009037
Rahul Sharma99770982019-03-06 17:05:26 +05309038 pthread_mutex_lock(&adev->lock);
9039 if (in_get_stream(adev, handle) != NULL) {
9040 ALOGW("%s, input stream already opened", __func__);
9041 ret = -EEXIST;
9042 }
9043 pthread_mutex_unlock(&adev->lock);
9044 if (ret)
9045 return ret;
9046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009047 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009048
9049 if (!in) {
9050 ALOGE("failed to allocate input stream");
9051 return -ENOMEM;
9052 }
9053
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309054 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309055 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9056 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009057 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009058 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009060 in->stream.common.get_sample_rate = in_get_sample_rate;
9061 in->stream.common.set_sample_rate = in_set_sample_rate;
9062 in->stream.common.get_buffer_size = in_get_buffer_size;
9063 in->stream.common.get_channels = in_get_channels;
9064 in->stream.common.get_format = in_get_format;
9065 in->stream.common.set_format = in_set_format;
9066 in->stream.common.standby = in_standby;
9067 in->stream.common.dump = in_dump;
9068 in->stream.common.set_parameters = in_set_parameters;
9069 in->stream.common.get_parameters = in_get_parameters;
9070 in->stream.common.add_audio_effect = in_add_audio_effect;
9071 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9072 in->stream.set_gain = in_set_gain;
9073 in->stream.read = in_read;
9074 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009075 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309076 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009077 in->stream.set_microphone_direction = in_set_microphone_direction;
9078 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009079 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009080
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009081 list_init(&in->device_list);
9082 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009083 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009084 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009085 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009086 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009087 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009088 in->bit_width = 16;
9089 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009090 in->direction = MIC_DIRECTION_UNSPECIFIED;
9091 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009092 list_init(&in->aec_list);
9093 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009094 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009095
Andy Hung94320602018-10-29 18:31:12 -07009096 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009097 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9098 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9099 /* Force channel config requested to mono if incall
9100 record is being requested for only uplink/downlink */
9101 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9102 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9103 ret = -EINVAL;
9104 goto err_open;
9105 }
9106 }
9107
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009108 if (is_usb_dev && may_use_hifi_record) {
9109 /* HiFi record selects an appropriate format, channel, rate combo
9110 depending on sink capabilities*/
9111 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9112 &config->format,
9113 &in->supported_formats[0],
9114 MAX_SUPPORTED_FORMATS,
9115 &config->channel_mask,
9116 &in->supported_channel_masks[0],
9117 MAX_SUPPORTED_CHANNEL_MASKS,
9118 &config->sample_rate,
9119 &in->supported_sample_rates[0],
9120 MAX_SUPPORTED_SAMPLE_RATES);
9121 if (ret != 0) {
9122 ret = -EINVAL;
9123 goto err_open;
9124 }
9125 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009126 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309127 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309128 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9129 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9130 in->config.format = PCM_FORMAT_S32_LE;
9131 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309132 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9133 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9134 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9135 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9136 bool ret_error = false;
9137 in->bit_width = 24;
9138 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9139 from HAL is 24_packed and 8_24
9140 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9141 24_packed return error indicating supported format is 24_packed
9142 *> In case of any other source requesting 24 bit or float return error
9143 indicating format supported is 16 bit only.
9144
9145 on error flinger will retry with supported format passed
9146 */
9147 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9148 (source != AUDIO_SOURCE_CAMCORDER)) {
9149 config->format = AUDIO_FORMAT_PCM_16_BIT;
9150 if (config->sample_rate > 48000)
9151 config->sample_rate = 48000;
9152 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009153 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9154 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309155 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9156 ret_error = true;
9157 }
9158
9159 if (ret_error) {
9160 ret = -EINVAL;
9161 goto err_open;
9162 }
9163 }
9164
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009165 in->channel_mask = config->channel_mask;
9166 in->format = config->format;
9167
9168 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309169
9170 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9171 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9172 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9173 else {
9174 ret = -EINVAL;
9175 goto err_open;
9176 }
9177 }
9178
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009179 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309180 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9181 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009182 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9183 is_low_latency = true;
9184#if LOW_LATENCY_CAPTURE_USE_CASE
9185 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9186#endif
9187 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009188 if (!in->realtime) {
9189 in->config = pcm_config_audio_capture;
9190 frame_size = audio_stream_in_frame_size(&in->stream);
9191 buffer_size = get_input_buffer_size(config->sample_rate,
9192 config->format,
9193 channel_count,
9194 is_low_latency);
9195 in->config.period_size = buffer_size / frame_size;
9196 in->config.rate = config->sample_rate;
9197 in->af_period_multiplier = 1;
9198 } else {
9199 // period size is left untouched for rt mode playback
9200 in->config = pcm_config_audio_capture_rt;
9201 in->af_period_multiplier = af_period_multiplier;
9202 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009203 }
9204
9205 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9206 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9207 in->realtime = 0;
9208 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9209 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009210 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009211 in->stream.start = in_start;
9212 in->stream.stop = in_stop;
9213 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9214 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009215 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009216 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009217 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9218 in->config = pcm_config_audio_capture;
9219 frame_size = audio_stream_in_frame_size(&in->stream);
9220 buffer_size = get_input_buffer_size(config->sample_rate,
9221 config->format,
9222 channel_count,
9223 false /*is_low_latency*/);
9224 in->config.period_size = buffer_size / frame_size;
9225 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009226 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009227 switch (config->format) {
9228 case AUDIO_FORMAT_PCM_32_BIT:
9229 in->bit_width = 32;
9230 break;
9231 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9232 case AUDIO_FORMAT_PCM_8_24_BIT:
9233 in->bit_width = 24;
9234 break;
9235 default:
9236 in->bit_width = 16;
9237 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009238 } else if (is_single_device_type_equal(&in->device_list,
9239 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9240 is_single_device_type_equal(&in->device_list,
9241 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009242 if (config->sample_rate == 0)
9243 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9244 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9245 config->sample_rate != 8000) {
9246 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9247 ret = -EINVAL;
9248 goto err_open;
9249 }
9250 if (config->format == AUDIO_FORMAT_DEFAULT)
9251 config->format = AUDIO_FORMAT_PCM_16_BIT;
9252 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9253 config->format = AUDIO_FORMAT_PCM_16_BIT;
9254 ret = -EINVAL;
9255 goto err_open;
9256 }
9257
9258 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
9259 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009260 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009261 in->af_period_multiplier = 1;
9262 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9263 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9264 (config->sample_rate == 8000 ||
9265 config->sample_rate == 16000 ||
9266 config->sample_rate == 32000 ||
9267 config->sample_rate == 48000) &&
9268 channel_count == 1) {
9269 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9270 in->config = pcm_config_audio_capture;
9271 frame_size = audio_stream_in_frame_size(&in->stream);
9272 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9273 config->sample_rate,
9274 config->format,
9275 channel_count, false /*is_low_latency*/);
9276 in->config.period_size = buffer_size / frame_size;
9277 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9278 in->config.rate = config->sample_rate;
9279 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009280 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309281 int ret_val;
9282 pthread_mutex_lock(&adev->lock);
9283 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9284 in, config, &channel_mask_updated);
9285 pthread_mutex_unlock(&adev->lock);
9286
9287 if (!ret_val) {
9288 if (channel_mask_updated == true) {
9289 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9290 __func__, config->channel_mask);
9291 ret = -EINVAL;
9292 goto err_open;
9293 }
9294 ALOGD("%s: created multi-channel session succesfully",__func__);
9295 } else if (audio_extn_compr_cap_enabled() &&
9296 audio_extn_compr_cap_format_supported(config->format) &&
9297 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9298 audio_extn_compr_cap_init(in);
9299 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309300 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309301 if (ret)
9302 goto err_open;
9303 } else {
9304 in->config = pcm_config_audio_capture;
9305 in->config.rate = config->sample_rate;
9306 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309307 in->format = config->format;
9308 frame_size = audio_stream_in_frame_size(&in->stream);
9309 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009310 config->format,
9311 channel_count,
9312 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009313 /* prevent division-by-zero */
9314 if (frame_size == 0) {
9315 ALOGE("%s: Error frame_size==0", __func__);
9316 ret = -EINVAL;
9317 goto err_open;
9318 }
9319
Revathi Uddarajud2634032017-12-07 14:42:34 +05309320 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009321 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009322
Revathi Uddarajud2634032017-12-07 14:42:34 +05309323 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9324 /* optionally use VOIP usecase depending on config(s) */
9325 ret = adev_update_voice_comm_input_stream(in, config);
9326 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009327
Revathi Uddarajud2634032017-12-07 14:42:34 +05309328 if (ret) {
9329 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9330 goto err_open;
9331 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009332 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309333
9334 /* assign concurrent capture usecase if record has to caried out from
9335 * actual hardware input source */
9336 if (audio_extn_is_concurrent_capture_enabled() &&
9337 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309338 /* Acquire lock to avoid two concurrent use cases initialized to
9339 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009340
Samyak Jainc37062f2019-04-25 18:41:06 +05309341 if (in->usecase == USECASE_AUDIO_RECORD) {
9342 pthread_mutex_lock(&adev->lock);
9343 if (!(adev->pcm_record_uc_state)) {
9344 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9345 adev->pcm_record_uc_state = 1;
9346 pthread_mutex_unlock(&adev->lock);
9347 } else {
9348 pthread_mutex_unlock(&adev->lock);
9349 /* Assign compress record use case for second record */
9350 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9351 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9352 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9353 if (audio_extn_cin_applicable_stream(in)) {
9354 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309355 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309356 if (ret)
9357 goto err_open;
9358 }
9359 }
9360 }
kunleiz28c73e72019-03-27 17:24:04 +08009361 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009362 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309363 if (audio_extn_ssr_get_stream() != in)
9364 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009365
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009366 in->sample_rate = in->config.rate;
9367
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309368 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9369 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009370 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009371 in->sample_rate, in->bit_width,
9372 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309373 register_format(in->format, in->supported_formats);
9374 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9375 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309376
Aalique Grahame22e49102018-12-18 14:23:57 -08009377 in->error_log = error_log_create(
9378 ERROR_LOG_ENTRIES,
9379 1000000000 /* aggregate consecutive identical errors within one second */);
9380
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009381 /* This stream could be for sound trigger lab,
9382 get sound trigger pcm if present */
9383 audio_extn_sound_trigger_check_and_get_session(in);
9384
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309385 lock_input_stream(in);
9386 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9387 pthread_mutex_lock(&adev->lock);
9388 in->card_status = adev->card_status;
9389 pthread_mutex_unlock(&adev->lock);
9390 pthread_mutex_unlock(&in->lock);
9391
Aalique Grahame22e49102018-12-18 14:23:57 -08009392 stream_app_type_cfg_init(&in->app_type_cfg);
9393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009394 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009395
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009396 ret = io_streams_map_insert(adev, &in->stream.common,
9397 handle, AUDIO_PATCH_HANDLE_NONE);
9398 if (ret != 0)
9399 goto err_open;
9400
Derek Chenf939fb72018-11-13 13:34:41 -08009401 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9402 calloc(1, sizeof(streams_input_ctxt_t));
9403 if (in_ctxt == NULL) {
9404 ALOGE("%s fail to allocate input ctxt", __func__);
9405 ret = -ENOMEM;
9406 goto err_open;
9407 }
9408 in_ctxt->input = in;
9409
9410 pthread_mutex_lock(&adev->lock);
9411 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9412 pthread_mutex_unlock(&adev->lock);
9413
Eric Laurent994a6932013-07-17 11:51:42 -07009414 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009415 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009416
9417err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309418 if (in->usecase == USECASE_AUDIO_RECORD) {
9419 pthread_mutex_lock(&adev->lock);
9420 adev->pcm_record_uc_state = 0;
9421 pthread_mutex_unlock(&adev->lock);
9422 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009423 free(in);
9424 *stream_in = NULL;
9425 return ret;
9426}
9427
9428static void adev_close_input_stream(struct audio_hw_device *dev,
9429 struct audio_stream_in *stream)
9430{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009431 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009432 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009433 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309434
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309435 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009436
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009437 if (in == NULL) {
9438 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9439 return;
9440 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009441 io_streams_map_remove(adev, in->capture_handle);
9442
kunleiz70e57612018-12-28 17:50:23 +08009443 /* must deregister from sndmonitor first to prevent races
9444 * between the callback and close_stream
9445 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309446 audio_extn_snd_mon_unregister_listener(stream);
9447
kunleiz70e57612018-12-28 17:50:23 +08009448 /* Disable echo reference if there are no active input, hfp call
9449 * and sound trigger while closing input stream
9450 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009451 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009452 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009453 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9454 struct listnode out_devices;
9455 list_init(&out_devices);
9456 platform_set_echo_reference(adev, false, &out_devices);
9457 } else
kunleiz70e57612018-12-28 17:50:23 +08009458 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309459
Weiyin Jiang2995f662019-04-17 14:25:12 +08009460 error_log_destroy(in->error_log);
9461 in->error_log = NULL;
9462
Pallavid7c7a272018-01-16 11:22:55 +05309463
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009464 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309465 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009466 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309467 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009468 if (ret != 0)
9469 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9470 __func__, ret);
9471 } else
9472 in_standby(&stream->common);
9473
Revathi Uddarajud2634032017-12-07 14:42:34 +05309474 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309475 if (in->usecase == USECASE_AUDIO_RECORD) {
9476 adev->pcm_record_uc_state = 0;
9477 }
9478
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009479 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9480 adev->enable_voicerx = false;
9481 }
9482
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009483 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009484 audio_extn_ssr_deinit();
9485 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009486
Garmond Leunge2433c32017-09-28 21:51:22 -07009487 if (audio_extn_ffv_get_stream() == in) {
9488 audio_extn_ffv_stream_deinit();
9489 }
9490
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309491 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009492 audio_extn_compr_cap_format_supported(in->config.format))
9493 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309494
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309495 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309496 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009497
Mingming Yinfd7607b2016-01-22 12:48:44 -08009498 if (in->is_st_session) {
9499 ALOGV("%s: sound trigger pcm stop lab", __func__);
9500 audio_extn_sound_trigger_stop_lab(in);
9501 }
Derek Chenf939fb72018-11-13 13:34:41 -08009502 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9503 if (in_ctxt != NULL) {
9504 list_remove(&in_ctxt->list);
9505 free(in_ctxt);
9506 } else {
9507 ALOGW("%s, input stream already closed", __func__);
9508 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009509 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309510 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009511 return;
9512}
9513
Aalique Grahame22e49102018-12-18 14:23:57 -08009514/* verifies input and output devices and their capabilities.
9515 *
9516 * This verification is required when enabling extended bit-depth or
9517 * sampling rates, as not all qcom products support it.
9518 *
9519 * Suitable for calling only on initialization such as adev_open().
9520 * It fills the audio_device use_case_table[] array.
9521 *
9522 * Has a side-effect that it needs to configure audio routing / devices
9523 * in order to power up the devices and read the device parameters.
9524 * It does not acquire any hw device lock. Should restore the devices
9525 * back to "normal state" upon completion.
9526 */
9527static int adev_verify_devices(struct audio_device *adev)
9528{
9529 /* enumeration is a bit difficult because one really wants to pull
9530 * the use_case, device id, etc from the hidden pcm_device_table[].
9531 * In this case there are the following use cases and device ids.
9532 *
9533 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9534 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9535 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9536 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9537 * [USECASE_AUDIO_RECORD] = {0, 0},
9538 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9539 * [USECASE_VOICE_CALL] = {2, 2},
9540 *
9541 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9542 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9543 */
9544
9545 /* should be the usecases enabled in adev_open_input_stream() */
9546 static const int test_in_usecases[] = {
9547 USECASE_AUDIO_RECORD,
9548 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9549 };
9550 /* should be the usecases enabled in adev_open_output_stream()*/
9551 static const int test_out_usecases[] = {
9552 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9553 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9554 };
9555 static const usecase_type_t usecase_type_by_dir[] = {
9556 PCM_PLAYBACK,
9557 PCM_CAPTURE,
9558 };
9559 static const unsigned flags_by_dir[] = {
9560 PCM_OUT,
9561 PCM_IN,
9562 };
9563
9564 size_t i;
9565 unsigned dir;
9566 const unsigned card_id = adev->snd_card;
9567
9568 for (dir = 0; dir < 2; ++dir) {
9569 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9570 const unsigned flags_dir = flags_by_dir[dir];
9571 const size_t testsize =
9572 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9573 const int *testcases =
9574 dir ? test_in_usecases : test_out_usecases;
9575 const audio_devices_t audio_device =
9576 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9577
9578 for (i = 0; i < testsize; ++i) {
9579 const audio_usecase_t audio_usecase = testcases[i];
9580 int device_id;
9581 struct pcm_params **pparams;
9582 struct stream_out out;
9583 struct stream_in in;
9584 struct audio_usecase uc_info;
9585 int retval;
9586
9587 pparams = &adev->use_case_table[audio_usecase];
9588 pcm_params_free(*pparams); /* can accept null input */
9589 *pparams = NULL;
9590
9591 /* find the device ID for the use case (signed, for error) */
9592 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9593 if (device_id < 0)
9594 continue;
9595
9596 /* prepare structures for device probing */
9597 memset(&uc_info, 0, sizeof(uc_info));
9598 uc_info.id = audio_usecase;
9599 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009600 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009601 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009602 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009603 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009604 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009605 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9606 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009607 }
9608 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009609 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009610 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009611 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009612 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009613 uc_info.in_snd_device = SND_DEVICE_NONE;
9614 uc_info.out_snd_device = SND_DEVICE_NONE;
9615 list_add_tail(&adev->usecase_list, &uc_info.list);
9616
9617 /* select device - similar to start_(in/out)put_stream() */
9618 retval = select_devices(adev, audio_usecase);
9619 if (retval >= 0) {
9620 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9621#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009622 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009623 if (*pparams) {
9624 ALOGV("%s: (%s) card %d device %d", __func__,
9625 dir ? "input" : "output", card_id, device_id);
9626 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9627 } else {
9628 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9629 }
9630#endif
9631 }
9632
9633 /* deselect device - similar to stop_(in/out)put_stream() */
9634 /* 1. Get and set stream specific mixer controls */
9635 retval = disable_audio_route(adev, &uc_info);
9636 /* 2. Disable the rx device */
9637 retval = disable_snd_device(adev,
9638 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9639 list_remove(&uc_info.list);
9640 }
9641 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009642 return 0;
9643}
9644
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009645int update_patch(unsigned int num_sources,
9646 const struct audio_port_config *sources,
9647 unsigned int num_sinks,
9648 const struct audio_port_config *sinks,
9649 audio_patch_handle_t handle,
9650 struct audio_patch_info *p_info,
9651 patch_type_t patch_type, bool new_patch)
9652{
9653 ALOGD("%s: enter", __func__);
9654
9655 if (p_info == NULL) {
9656 ALOGE("%s: Invalid patch pointer", __func__);
9657 return -EINVAL;
9658 }
9659
9660 if (new_patch) {
9661 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9662 if (p_info->patch == NULL) {
9663 ALOGE("%s: Could not allocate patch", __func__);
9664 return -ENOMEM;
9665 }
9666 }
9667
9668 p_info->patch->id = handle;
9669 p_info->patch->num_sources = num_sources;
9670 p_info->patch->num_sinks = num_sinks;
9671
9672 for (int i = 0; i < num_sources; i++)
9673 p_info->patch->sources[i] = sources[i];
9674 for (int i = 0; i < num_sinks; i++)
9675 p_info->patch->sinks[i] = sinks[i];
9676
9677 p_info->patch_type = patch_type;
9678 return 0;
9679}
9680
9681audio_patch_handle_t generate_patch_handle()
9682{
9683 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9684 if (++patch_handle < 0)
9685 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9686 return patch_handle;
9687}
9688
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309689int adev_create_audio_patch(struct audio_hw_device *dev,
9690 unsigned int num_sources,
9691 const struct audio_port_config *sources,
9692 unsigned int num_sinks,
9693 const struct audio_port_config *sinks,
9694 audio_patch_handle_t *handle)
9695{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009696 int ret = 0;
9697 struct audio_device *adev = (struct audio_device *)dev;
9698 struct audio_patch_info *p_info = NULL;
9699 patch_type_t patch_type = PATCH_NONE;
9700 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9701 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9702 struct audio_stream_info *s_info = NULL;
9703 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009704 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009705 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9706 bool new_patch = false;
9707 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309708
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009709 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9710 num_sources, num_sinks, *handle);
9711
9712 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9713 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9714 ALOGE("%s: Invalid patch arguments", __func__);
9715 ret = -EINVAL;
9716 goto done;
9717 }
9718
9719 if (num_sources > 1) {
9720 ALOGE("%s: Multiple sources are not supported", __func__);
9721 ret = -EINVAL;
9722 goto done;
9723 }
9724
9725 if (sources == NULL || sinks == NULL) {
9726 ALOGE("%s: Invalid sources or sinks port config", __func__);
9727 ret = -EINVAL;
9728 goto done;
9729 }
9730
9731 ALOGV("%s: source role %d, source type %d", __func__,
9732 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009733 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009734
9735 // Populate source/sink information and fetch stream info
9736 switch (sources[0].type) {
9737 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9738 device_type = sources[0].ext.device.type;
9739 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009740 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009741 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9742 patch_type = PATCH_CAPTURE;
9743 io_handle = sinks[0].ext.mix.handle;
9744 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009745 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009746 __func__, device_type, io_handle);
9747 } else {
9748 // Device to device patch is not implemented.
9749 // This space will need changes if audio HAL
9750 // handles device to device patches in the future.
9751 patch_type = PATCH_DEVICE_LOOPBACK;
9752 }
9753 break;
9754 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9755 io_handle = sources[0].ext.mix.handle;
9756 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009757 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009758 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009759 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009760 }
9761 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009762 ALOGD("%s: Playback patch from mix handle %d to device %x",
9763 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009764 break;
9765 case AUDIO_PORT_TYPE_SESSION:
9766 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009767 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9768 ret = -EINVAL;
9769 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009770 }
9771
9772 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009773
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009774 // Generate patch info and update patch
9775 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009776 *handle = generate_patch_handle();
9777 p_info = (struct audio_patch_info *)
9778 calloc(1, sizeof(struct audio_patch_info));
9779 if (p_info == NULL) {
9780 ALOGE("%s: Failed to allocate memory", __func__);
9781 pthread_mutex_unlock(&adev->lock);
9782 ret = -ENOMEM;
9783 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009784 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009785 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009786 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009787 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009788 if (p_info == NULL) {
9789 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9790 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009791 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009792 ret = -EINVAL;
9793 goto done;
9794 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009795 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009796 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009797 *handle, p_info, patch_type, new_patch);
9798
9799 // Fetch stream info of associated mix for playback or capture patches
9800 if (p_info->patch_type == PATCH_PLAYBACK ||
9801 p_info->patch_type == PATCH_CAPTURE) {
9802 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9803 if (s_info == NULL) {
9804 ALOGE("%s: Failed to obtain stream info", __func__);
9805 if (new_patch)
9806 free(p_info);
9807 pthread_mutex_unlock(&adev->lock);
9808 ret = -EINVAL;
9809 goto done;
9810 }
9811 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9812 s_info->patch_handle = *handle;
9813 stream = s_info->stream;
9814 }
9815 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009816
9817 // Update routing for stream
9818 if (stream != NULL) {
9819 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009820 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009821 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009822 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009823 if (ret < 0) {
9824 pthread_mutex_lock(&adev->lock);
9825 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9826 if (new_patch)
9827 free(p_info);
9828 pthread_mutex_unlock(&adev->lock);
9829 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9830 goto done;
9831 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009832 }
9833
9834 // Add new patch to patch map
9835 if (!ret && new_patch) {
9836 pthread_mutex_lock(&adev->lock);
9837 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009838 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009839 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009840 }
9841
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009842done:
9843 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009844 num_sources,
9845 sources,
9846 num_sinks,
9847 sinks,
9848 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009849 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009850 num_sources,
9851 sources,
9852 num_sinks,
9853 sinks,
9854 handle);
9855 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309856}
9857
9858int adev_release_audio_patch(struct audio_hw_device *dev,
9859 audio_patch_handle_t handle)
9860{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009861 struct audio_device *adev = (struct audio_device *) dev;
9862 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009863 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009864 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -08009865
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009866 if (handle == AUDIO_PATCH_HANDLE_NONE) {
9867 ALOGE("%s: Invalid patch handle %d", __func__, handle);
9868 ret = -EINVAL;
9869 goto done;
9870 }
9871
9872 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009873 pthread_mutex_lock(&adev->lock);
9874 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009875 if (p_info == NULL) {
9876 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009877 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009878 ret = -EINVAL;
9879 goto done;
9880 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009881 struct audio_patch *patch = p_info->patch;
9882 if (patch == NULL) {
9883 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009884 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009885 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009886 goto done;
9887 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009888 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9889 switch (patch->sources[0].type) {
9890 case AUDIO_PORT_TYPE_MIX:
9891 io_handle = patch->sources[0].ext.mix.handle;
9892 break;
9893 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009894 if (p_info->patch_type == PATCH_CAPTURE)
9895 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009896 break;
9897 case AUDIO_PORT_TYPE_SESSION:
9898 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009899 pthread_mutex_unlock(&adev->lock);
9900 ret = -EINVAL;
9901 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009902 }
9903
9904 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009905 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009906 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009907 if (patch_type == PATCH_PLAYBACK ||
9908 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009909 struct audio_stream_info *s_info =
9910 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9911 if (s_info == NULL) {
9912 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
9913 pthread_mutex_unlock(&adev->lock);
9914 goto done;
9915 }
9916 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9917 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009918 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009919 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009920
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009921 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009922 struct listnode devices;
9923 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009924 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009925 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009926 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009927 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009928 }
9929
9930 if (ret < 0)
9931 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9932
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009933done:
9934 audio_extn_hw_loopback_release_audio_patch(dev, handle);
9935 audio_extn_auto_hal_release_audio_patch(dev, handle);
9936
9937 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -08009938 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309939}
9940
9941int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9942{
Derek Chenf13dd492018-11-13 14:53:51 -08009943 int ret = 0;
9944
9945 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9946 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9947 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309948}
9949
9950int adev_set_audio_port_config(struct audio_hw_device *dev,
9951 const struct audio_port_config *config)
9952{
Derek Chenf13dd492018-11-13 14:53:51 -08009953 int ret = 0;
9954
9955 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9956 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9957 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309958}
9959
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009960static int adev_dump(const audio_hw_device_t *device __unused,
9961 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009962{
9963 return 0;
9964}
9965
9966static int adev_close(hw_device_t *device)
9967{
Aalique Grahame22e49102018-12-18 14:23:57 -08009968 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309969 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009970
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309971 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009972 return 0;
9973
9974 pthread_mutex_lock(&adev_init_lock);
9975
9976 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309977 if (audio_extn_spkr_prot_is_enabled())
9978 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +05309979 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309980 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009981 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009982 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009983 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009984 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309985 audio_extn_utils_release_streams_cfg_lists(
9986 &adev->streams_output_cfg_list,
9987 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309988 if (audio_extn_qap_is_enabled())
9989 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309990 if (audio_extn_qaf_is_enabled())
9991 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009992 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009993 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009994 free(adev->snd_dev_ref_cnt);
9995 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009996 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9997 pcm_params_free(adev->use_case_table[i]);
9998 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009999 if (adev->adm_deinit)
10000 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010001 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010002 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010003 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010004 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010005 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010006 if (adev->device_cfg_params) {
10007 free(adev->device_cfg_params);
10008 adev->device_cfg_params = NULL;
10009 }
Derek Chend2530072014-11-24 12:39:14 -080010010 if(adev->ext_hw_plugin)
10011 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010012 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010013 free_map(adev->patch_map);
10014 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010015 free(device);
10016 adev = NULL;
10017 }
10018 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010019 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010020 return 0;
10021}
10022
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010023/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10024 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10025 * just that it _might_ work.
10026 */
10027static int period_size_is_plausible_for_low_latency(int period_size)
10028{
10029 switch (period_size) {
10030 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010031 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010032 case 240:
10033 case 320:
10034 case 480:
10035 return 1;
10036 default:
10037 return 0;
10038 }
10039}
10040
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010041static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10042{
10043 bool is_snd_card_status = false;
10044 bool is_ext_device_status = false;
10045 char value[32];
10046 int card = -1;
10047 card_status_t status;
10048
10049 if (cookie != adev || !parms)
10050 return;
10051
10052 if (!parse_snd_card_status(parms, &card, &status)) {
10053 is_snd_card_status = true;
10054 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10055 is_ext_device_status = true;
10056 } else {
10057 // not a valid event
10058 return;
10059 }
10060
10061 pthread_mutex_lock(&adev->lock);
10062 if (card == adev->snd_card || is_ext_device_status) {
10063 if (is_snd_card_status && adev->card_status != status) {
10064 adev->card_status = status;
10065 platform_snd_card_update(adev->platform, status);
10066 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010067 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010068 if (status == CARD_STATUS_OFFLINE)
10069 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010070 } else if (is_ext_device_status) {
10071 platform_set_parameters(adev->platform, parms);
10072 }
10073 }
10074 pthread_mutex_unlock(&adev->lock);
10075 return;
10076}
10077
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010078/* out and adev lock held */
10079static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10080{
10081 struct audio_usecase *uc_info;
10082 float left_p;
10083 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010084 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010085
10086 uc_info = get_usecase_from_list(adev, out->usecase);
10087 if (uc_info == NULL) {
10088 ALOGE("%s: Could not find the usecase (%d) in the list",
10089 __func__, out->usecase);
10090 return -EINVAL;
10091 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010092 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010093
10094 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10095 out->usecase, use_case_table[out->usecase]);
10096
10097 if (restore) {
10098 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010099 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010100 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010101 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10102 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010103 pthread_mutex_lock(&out->compr_mute_lock);
10104 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010105 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010106 out->a2dp_compress_mute = false;
10107 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10108 }
10109 pthread_mutex_unlock(&out->compr_mute_lock);
10110 }
10111 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010112 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10113 // mute compress stream if suspended
10114 pthread_mutex_lock(&out->compr_mute_lock);
10115 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010116 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010117 assign_devices(&devices, &out->device_list);
10118 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010119 left_p = out->volume_l;
10120 right_p = out->volume_r;
10121 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10122 compress_pause(out->compr);
10123 out_set_compr_volume(&out->stream, (float)0, (float)0);
10124 out->a2dp_compress_mute = true;
10125 select_devices(adev, out->usecase);
10126 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10127 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010128 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010129 out->volume_l = left_p;
10130 out->volume_r = right_p;
10131 }
Zhou Songc576a452019-09-09 14:17:40 +080010132 pthread_mutex_unlock(&out->compr_mute_lock);
10133 } else {
10134 // tear down a2dp path for non offloaded streams
10135 if (audio_extn_a2dp_source_is_suspended())
10136 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010137 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010138 }
10139 ALOGV("%s: exit", __func__);
10140 return 0;
10141}
10142
10143int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10144{
10145 int ret = 0;
10146
10147 lock_output_stream(out);
10148 pthread_mutex_lock(&adev->lock);
10149
10150 ret = check_a2dp_restore_l(adev, out, restore);
10151
10152 pthread_mutex_unlock(&adev->lock);
10153 pthread_mutex_unlock(&out->lock);
10154 return ret;
10155}
10156
Haynes Mathew George01156f92018-04-13 15:29:54 -070010157void adev_on_battery_status_changed(bool charging)
10158{
10159 pthread_mutex_lock(&adev->lock);
10160 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10161 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010162 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010163 pthread_mutex_unlock(&adev->lock);
10164}
10165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010166static int adev_open(const hw_module_t *module, const char *name,
10167 hw_device_t **device)
10168{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010169 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010170 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010171 char mixer_ctl_name[128] = {0};
10172 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010173
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010174 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010175 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10176
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010177 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010178 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010179 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010180 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010181 ALOGD("%s: returning existing instance of adev", __func__);
10182 ALOGD("%s: exit", __func__);
10183 pthread_mutex_unlock(&adev_init_lock);
10184 return 0;
10185 }
10186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010187 adev = calloc(1, sizeof(struct audio_device));
10188
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010189 if (!adev) {
10190 pthread_mutex_unlock(&adev_init_lock);
10191 return -ENOMEM;
10192 }
10193
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010194 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10195
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010196 // register audio ext hidl at the earliest
10197 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010198#ifdef DYNAMIC_LOG_ENABLED
10199 register_for_dynamic_logging("hal");
10200#endif
10201
Derek Chenf939fb72018-11-13 13:34:41 -080010202 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010203 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010204 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10205 maj_version = atoi(value);
10206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010207 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010208 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010209 adev->device.common.module = (struct hw_module_t *)module;
10210 adev->device.common.close = adev_close;
10211
10212 adev->device.init_check = adev_init_check;
10213 adev->device.set_voice_volume = adev_set_voice_volume;
10214 adev->device.set_master_volume = adev_set_master_volume;
10215 adev->device.get_master_volume = adev_get_master_volume;
10216 adev->device.set_master_mute = adev_set_master_mute;
10217 adev->device.get_master_mute = adev_get_master_mute;
10218 adev->device.set_mode = adev_set_mode;
10219 adev->device.set_mic_mute = adev_set_mic_mute;
10220 adev->device.get_mic_mute = adev_get_mic_mute;
10221 adev->device.set_parameters = adev_set_parameters;
10222 adev->device.get_parameters = adev_get_parameters;
10223 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10224 adev->device.open_output_stream = adev_open_output_stream;
10225 adev->device.close_output_stream = adev_close_output_stream;
10226 adev->device.open_input_stream = adev_open_input_stream;
10227 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010228 adev->device.create_audio_patch = adev_create_audio_patch;
10229 adev->device.release_audio_patch = adev_release_audio_patch;
10230 adev->device.get_audio_port = adev_get_audio_port;
10231 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010232 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010233 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010234
10235 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010236 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010237 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010238 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010239 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010240 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010241 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010242 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010243 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010244 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010245 /* Init audio and voice feature */
10246 audio_extn_feature_init();
10247 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010248 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010249 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010250 list_init(&adev->active_inputs_list);
10251 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010252 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010253 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10254 audio_extn_utils_hash_eq);
10255 if (!adev->io_streams_map) {
10256 ALOGE("%s: Could not create io streams map", __func__);
10257 ret = -ENOMEM;
10258 goto adev_open_err;
10259 }
10260 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10261 audio_extn_utils_hash_eq);
10262 if (!adev->patch_map) {
10263 ALOGE("%s: Could not create audio patch map", __func__);
10264 ret = -ENOMEM;
10265 goto adev_open_err;
10266 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010267 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010268 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010269 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010270 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010271 adev->perf_lock_opts[0] = 0x101;
10272 adev->perf_lock_opts[1] = 0x20E;
10273 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010274 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010275 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010276 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010277 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010279 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010280 adev->platform = platform_init(adev);
10281 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010282 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010283 ret = -EINVAL;
10284 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010285 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010286
Aalique Grahame22e49102018-12-18 14:23:57 -080010287 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010288 if (audio_extn_qap_is_enabled()) {
10289 ret = audio_extn_qap_init(adev);
10290 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010291 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010292 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010293 }
10294 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10295 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10296 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010297
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010298 if (audio_extn_qaf_is_enabled()) {
10299 ret = audio_extn_qaf_init(adev);
10300 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010301 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010302 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010303 }
10304
10305 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10306 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10307 }
10308
Derek Chenae7b0342019-02-08 15:17:04 -080010309 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010310 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10311
Eric Laurentc4aef752013-09-12 17:45:53 -070010312 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10313 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10314 if (adev->visualizer_lib == NULL) {
10315 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10316 } else {
10317 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10318 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010319 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010320 "visualizer_hal_start_output");
10321 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010322 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010323 "visualizer_hal_stop_output");
10324 }
10325 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010326 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010327 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010328 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010329 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010330 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010331 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010332
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010333 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10334 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10335 if (adev->offload_effects_lib == NULL) {
10336 ALOGE("%s: DLOPEN failed for %s", __func__,
10337 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10338 } else {
10339 ALOGV("%s: DLOPEN successful for %s", __func__,
10340 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10341 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010342 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010343 "offload_effects_bundle_hal_start_output");
10344 adev->offload_effects_stop_output =
10345 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10346 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010347 adev->offload_effects_set_hpx_state =
10348 (int (*)(bool))dlsym(adev->offload_effects_lib,
10349 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010350 adev->offload_effects_get_parameters =
10351 (void (*)(struct str_parms *, struct str_parms *))
10352 dlsym(adev->offload_effects_lib,
10353 "offload_effects_bundle_get_parameters");
10354 adev->offload_effects_set_parameters =
10355 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10356 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010357 }
10358 }
10359
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010360 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10361 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10362 if (adev->adm_lib == NULL) {
10363 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10364 } else {
10365 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10366 adev->adm_init = (adm_init_t)
10367 dlsym(adev->adm_lib, "adm_init");
10368 adev->adm_deinit = (adm_deinit_t)
10369 dlsym(adev->adm_lib, "adm_deinit");
10370 adev->adm_register_input_stream = (adm_register_input_stream_t)
10371 dlsym(adev->adm_lib, "adm_register_input_stream");
10372 adev->adm_register_output_stream = (adm_register_output_stream_t)
10373 dlsym(adev->adm_lib, "adm_register_output_stream");
10374 adev->adm_deregister_stream = (adm_deregister_stream_t)
10375 dlsym(adev->adm_lib, "adm_deregister_stream");
10376 adev->adm_request_focus = (adm_request_focus_t)
10377 dlsym(adev->adm_lib, "adm_request_focus");
10378 adev->adm_abandon_focus = (adm_abandon_focus_t)
10379 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010380 adev->adm_set_config = (adm_set_config_t)
10381 dlsym(adev->adm_lib, "adm_set_config");
10382 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10383 dlsym(adev->adm_lib, "adm_request_focus_v2");
10384 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10385 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10386 adev->adm_on_routing_change = (adm_on_routing_change_t)
10387 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010388 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10389 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010390 }
10391 }
10392
Aalique Grahame22e49102018-12-18 14:23:57 -080010393 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010394 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010395 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010396 //initialize this to false for now,
10397 //this will be set to true through set param
10398 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010399
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010400 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010401 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010402
10403 if (k_enable_extended_precision)
10404 adev_verify_devices(adev);
10405
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010406 adev->dsp_bit_width_enforce_mode =
10407 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010408
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010409 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10410 &adev->streams_output_cfg_list,
10411 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010412
Kiran Kandi910e1862013-10-29 13:29:42 -070010413 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010414
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010415 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010416 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010417 trial = atoi(value);
10418 if (period_size_is_plausible_for_low_latency(trial)) {
10419 pcm_config_low_latency.period_size = trial;
10420 pcm_config_low_latency.start_threshold = trial / 4;
10421 pcm_config_low_latency.avail_min = trial / 4;
10422 configured_low_latency_capture_period_size = trial;
10423 }
10424 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010425 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10426 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010427 trial = atoi(value);
10428 if (period_size_is_plausible_for_low_latency(trial)) {
10429 configured_low_latency_capture_period_size = trial;
10430 }
10431 }
10432
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010433 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10434
Eric Laurent4b084132018-10-19 17:33:43 -070010435 adev->camera_orientation = CAMERA_DEFAULT;
10436
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010437 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010438 af_period_multiplier = atoi(value);
10439 if (af_period_multiplier < 0)
10440 af_period_multiplier = 2;
10441 else if (af_period_multiplier > 4)
10442 af_period_multiplier = 4;
10443
10444 ALOGV("new period_multiplier = %d", af_period_multiplier);
10445 }
10446
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010447 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010448
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010449 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010450 pthread_mutex_unlock(&adev_init_lock);
10451
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010452 if (adev->adm_init)
10453 adev->adm_data = adev->adm_init();
10454
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010455 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010456 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010457 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010458
10459 audio_extn_snd_mon_init();
10460 pthread_mutex_lock(&adev->lock);
10461 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10462 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010463 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10464 /*
10465 * if the battery state callback happens before charging can be queried,
10466 * it will be guarded with the adev->lock held in the cb function and so
10467 * the callback value will reflect the latest state
10468 */
10469 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010470 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010471 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010472 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010473 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010474 /* Allocate memory for Device config params */
10475 adev->device_cfg_params = (struct audio_device_config_param*)
10476 calloc(platform_get_max_codec_backend(),
10477 sizeof(struct audio_device_config_param));
10478 if (adev->device_cfg_params == NULL)
10479 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010480
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010481 /*
10482 * Check if new PSPD matrix mixer control is supported. If not
10483 * supported, then set flag so that old mixer ctrl is sent while
10484 * sending pspd coefficients on older kernel version. Query mixer
10485 * control for default pcm id and channel value one.
10486 */
10487 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10488 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10489
10490 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10491 if (!ctl) {
10492 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10493 __func__, mixer_ctl_name);
10494 adev->use_old_pspd_mix_ctrl = true;
10495 }
10496
Eric Laurent994a6932013-07-17 11:51:42 -070010497 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010498 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010499
10500adev_open_err:
10501 free_map(adev->patch_map);
10502 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010503 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010504 pthread_mutex_destroy(&adev->lock);
10505 free(adev);
10506 adev = NULL;
10507 *device = NULL;
10508 pthread_mutex_unlock(&adev_init_lock);
10509 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010510}
10511
10512static struct hw_module_methods_t hal_module_methods = {
10513 .open = adev_open,
10514};
10515
10516struct audio_module HAL_MODULE_INFO_SYM = {
10517 .common = {
10518 .tag = HARDWARE_MODULE_TAG,
10519 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10520 .hal_api_version = HARDWARE_HAL_API_VERSION,
10521 .id = AUDIO_HARDWARE_MODULE_ID,
10522 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010523 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010524 .methods = &hal_module_methods,
10525 },
10526};