blob: 2a33f9e3b971329500608ae40797a13c5c94df09 [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",
Zhou Song62ea0282020-03-22 19:53:01 +0800386 [USECASE_AUDIO_RECORD_AFE_PROXY2] = "afe-proxy-record2",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530387 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700388
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530389 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530390 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
391 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700392
393 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
394 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530395 /* For Interactive Audio Streams */
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
401 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
402 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
403 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700404
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800405 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
406
Derek Chenf6318be2017-06-12 17:16:24 -0400407 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
408
409 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
410 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
411 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
412 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700413 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530414 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700415};
416
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700417static const audio_usecase_t offload_usecases[] = {
418 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700419 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
420 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
421 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
422 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
426 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700427};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800428
Varun Balaraje49253e2017-07-06 19:48:56 +0530429static const audio_usecase_t interactive_usecases[] = {
430 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
432 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
437 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
438};
439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800440#define STRING_TO_ENUM(string) { #string, string }
441
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800442struct string_to_enum {
443 const char *name;
444 uint32_t value;
445};
446
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700447static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800448 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
450 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800455 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700456 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
457 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
458 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
459 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
461 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
466 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800467};
468
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700469static const struct string_to_enum formats_name_to_enum_table[] = {
470 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
471 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
472 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700473 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
474 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
475 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700476 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800477 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
478 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700479 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800480};
481
482//list of all supported sample rates by HDMI specification.
483static const int out_hdmi_sample_rates[] = {
484 32000, 44100, 48000, 88200, 96000, 176400, 192000,
485};
486
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700487static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800488 STRING_TO_ENUM(32000),
489 STRING_TO_ENUM(44100),
490 STRING_TO_ENUM(48000),
491 STRING_TO_ENUM(88200),
492 STRING_TO_ENUM(96000),
493 STRING_TO_ENUM(176400),
494 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800495 STRING_TO_ENUM(352800),
496 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700497};
498
Carter Hsu2e429db2019-05-14 18:50:52 +0800499struct in_effect_list {
500 struct listnode list;
501 effect_handle_t handle;
502};
503
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700504static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700505static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700506static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700507//cache last MBDRC cal step level
508static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700509
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530510static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
511static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700512static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800513static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530514static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530515
Derek Chen6f293672019-04-01 01:40:24 -0700516static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
517static void in_snd_mon_cb(void * stream, struct str_parms * parms);
518static void out_snd_mon_cb(void * stream, struct str_parms * parms);
519
Zhou Song331c8e52019-08-26 14:16:12 +0800520static int configure_btsco_sample_rate(snd_device_t snd_device);
521
Vatsal Buchac09ae062018-11-14 13:25:08 +0530522#ifdef AUDIO_FEATURE_ENABLED_GCOV
523extern void __gcov_flush();
524static void enable_gcov()
525{
526 __gcov_flush();
527}
528#else
529static void enable_gcov()
530{
531}
532#endif
533
justinweng20fb6d82019-02-21 18:49:00 -0700534static int in_set_microphone_direction(const struct audio_stream_in *stream,
535 audio_microphone_direction_t dir);
536static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
537
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700538static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
539 int flags __unused)
540{
541 int dir = 0;
542 switch (uc_id) {
543 case USECASE_AUDIO_RECORD_LOW_LATENCY:
544 dir = 1;
545 case USECASE_AUDIO_PLAYBACK_ULL:
546 break;
547 default:
548 return false;
549 }
550
551 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
552 PCM_PLAYBACK : PCM_CAPTURE);
553 if (adev->adm_is_noirq_avail)
554 return adev->adm_is_noirq_avail(adev->adm_data,
555 adev->snd_card, dev_id, dir);
556 return false;
557}
558
559static void register_out_stream(struct stream_out *out)
560{
561 struct audio_device *adev = out->dev;
562 if (is_offload_usecase(out->usecase) ||
563 !adev->adm_register_output_stream)
564 return;
565
566 // register stream first for backward compatibility
567 adev->adm_register_output_stream(adev->adm_data,
568 out->handle,
569 out->flags);
570
571 if (!adev->adm_set_config)
572 return;
573
574 if (out->realtime)
575 adev->adm_set_config(adev->adm_data,
576 out->handle,
577 out->pcm, &out->config);
578}
579
580static void register_in_stream(struct stream_in *in)
581{
582 struct audio_device *adev = in->dev;
583 if (!adev->adm_register_input_stream)
584 return;
585
586 adev->adm_register_input_stream(adev->adm_data,
587 in->capture_handle,
588 in->flags);
589
590 if (!adev->adm_set_config)
591 return;
592
593 if (in->realtime)
594 adev->adm_set_config(adev->adm_data,
595 in->capture_handle,
596 in->pcm,
597 &in->config);
598}
599
600static void request_out_focus(struct stream_out *out, long ns)
601{
602 struct audio_device *adev = out->dev;
603
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700604 if (adev->adm_request_focus_v2)
605 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
606 else if (adev->adm_request_focus)
607 adev->adm_request_focus(adev->adm_data, out->handle);
608}
609
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700610static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700611{
612 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700613 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700614
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700615 if (adev->adm_request_focus_v2_1)
616 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
617 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700618 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
619 else if (adev->adm_request_focus)
620 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700621
622 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700623}
624
625static void release_out_focus(struct stream_out *out)
626{
627 struct audio_device *adev = out->dev;
628
629 if (adev->adm_abandon_focus)
630 adev->adm_abandon_focus(adev->adm_data, out->handle);
631}
632
633static void release_in_focus(struct stream_in *in)
634{
635 struct audio_device *adev = in->dev;
636 if (adev->adm_abandon_focus)
637 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
638}
639
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530640static int parse_snd_card_status(struct str_parms *parms, int *card,
641 card_status_t *status)
642{
643 char value[32]={0};
644 char state[32]={0};
645
646 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
647 if (ret < 0)
648 return -1;
649
650 // sscanf should be okay as value is of max length 32.
651 // same as sizeof state.
652 if (sscanf(value, "%d,%s", card, state) < 2)
653 return -1;
654
655 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
656 CARD_STATUS_OFFLINE;
657 return 0;
658}
659
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700660static inline void adjust_frames_for_device_delay(struct stream_out *out,
661 uint32_t *dsp_frames) {
662 // Adjustment accounts for A2dp encoder latency with offload usecases
663 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800664 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700665 unsigned long offset =
666 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
667 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
668 }
669}
670
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700671static inline bool free_entry(void *key __unused,
672 void *value, void *context __unused)
673{
674 free(value);
675 return true;
676}
677
678static inline void free_map(Hashmap *map)
679{
680 if (map) {
681 hashmapForEach(map, free_entry, (void *) NULL);
682 hashmapFree(map);
683 }
684}
685
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800686static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700687 audio_patch_handle_t patch_handle)
688{
689 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
690 return;
691
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700692 struct audio_patch_info *p_info =
693 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
694 if (p_info) {
695 ALOGV("%s: Remove patch %d", __func__, patch_handle);
696 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
697 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700698 free(p_info);
699 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700700}
701
702static inline int io_streams_map_insert(struct audio_device *adev,
703 struct audio_stream *stream,
704 audio_io_handle_t handle,
705 audio_patch_handle_t patch_handle)
706{
707 struct audio_stream_info *s_info =
708 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
709
710 if (s_info == NULL) {
711 ALOGE("%s: Could not allocate stream info", __func__);
712 return -ENOMEM;
713 }
714 s_info->stream = stream;
715 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700716
717 pthread_mutex_lock(&adev->lock);
718 struct audio_stream_info *stream_info =
719 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700720 if (stream_info != NULL)
721 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800722 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700723 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
724 return 0;
725}
726
727static inline void io_streams_map_remove(struct audio_device *adev,
728 audio_io_handle_t handle)
729{
730 pthread_mutex_lock(&adev->lock);
731 struct audio_stream_info *s_info =
732 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700733 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800734 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700735 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800736 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700737 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800738done:
739 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700740 return;
741}
742
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800743static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700744 audio_patch_handle_t handle)
745{
746 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700747 p_info = (struct audio_patch_info *)
748 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700749 return p_info;
750}
751
vivek mehtaa76401a2015-04-24 14:12:15 -0700752__attribute__ ((visibility ("default")))
753bool audio_hw_send_gain_dep_calibration(int level) {
754 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700755 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700756
757 pthread_mutex_lock(&adev_init_lock);
758
759 if (adev != NULL && adev->platform != NULL) {
760 pthread_mutex_lock(&adev->lock);
761 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700762
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530763 // cache level info for any of the use case which
764 // was not started.
765 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700766
vivek mehtaa76401a2015-04-24 14:12:15 -0700767 pthread_mutex_unlock(&adev->lock);
768 } else {
769 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
770 }
771
772 pthread_mutex_unlock(&adev_init_lock);
773
774 return ret_val;
775}
776
Ashish Jain5106d362016-05-11 19:23:33 +0530777static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
778{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800779 bool gapless_enabled = false;
780 const char *mixer_ctl_name = "Compress Gapless Playback";
781 struct mixer_ctl *ctl;
782
783 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700784 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530785
786 /*Disable gapless if its AV playback*/
787 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800788
789 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
790 if (!ctl) {
791 ALOGE("%s: Could not get ctl for mixer cmd - %s",
792 __func__, mixer_ctl_name);
793 return -EINVAL;
794 }
795
796 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
797 ALOGE("%s: Could not set gapless mode %d",
798 __func__, gapless_enabled);
799 return -EINVAL;
800 }
801 return 0;
802}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700803
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700804__attribute__ ((visibility ("default")))
805int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
806 int table_size) {
807 int ret_val = 0;
808 ALOGV("%s: enter ... ", __func__);
809
810 pthread_mutex_lock(&adev_init_lock);
811 if (adev == NULL) {
812 ALOGW("%s: adev is NULL .... ", __func__);
813 goto done;
814 }
815
816 pthread_mutex_lock(&adev->lock);
817 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
818 pthread_mutex_unlock(&adev->lock);
819done:
820 pthread_mutex_unlock(&adev_init_lock);
821 ALOGV("%s: exit ... ", __func__);
822 return ret_val;
823}
824
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800825bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800826{
827 bool ret = false;
828 ALOGV("%s: enter ...", __func__);
829
830 pthread_mutex_lock(&adev_init_lock);
831
832 if (adev != NULL && adev->platform != NULL) {
833 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800834 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800835 pthread_mutex_unlock(&adev->lock);
836 }
837
838 pthread_mutex_unlock(&adev_init_lock);
839
840 ALOGV("%s: exit with ret %d", __func__, ret);
841 return ret;
842}
Aalique Grahame22e49102018-12-18 14:23:57 -0800843
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700844static bool is_supported_format(audio_format_t format)
845{
Eric Laurent86e17132013-09-12 17:49:30 -0700846 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530847 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530848 format == AUDIO_FORMAT_AAC_LC ||
849 format == AUDIO_FORMAT_AAC_HE_V1 ||
850 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530851 format == AUDIO_FORMAT_AAC_ADTS_LC ||
852 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
853 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530854 format == AUDIO_FORMAT_AAC_LATM_LC ||
855 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
856 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530857 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
858 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530859 format == AUDIO_FORMAT_PCM_FLOAT ||
860 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700861 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530862 format == AUDIO_FORMAT_AC3 ||
863 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700864 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530865 format == AUDIO_FORMAT_DTS ||
866 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800867 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530868 format == AUDIO_FORMAT_ALAC ||
869 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530870 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530871 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800872 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530873 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700874 format == AUDIO_FORMAT_APTX ||
875 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800876 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700877
878 return false;
879}
880
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700881static inline bool is_mmap_usecase(audio_usecase_t uc_id)
882{
883 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
Zhou Song62ea0282020-03-22 19:53:01 +0800884 (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY2) ||
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700885 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
886}
887
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700888static inline bool is_valid_volume(float left, float right)
889{
890 return ((left >= 0.0f && right >= 0.0f) ? true : false);
891}
892
Avinash Vaish71a8b972014-07-24 15:36:33 +0530893static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
894 struct audio_usecase *uc_info)
895{
896 struct listnode *node;
897 struct audio_usecase *usecase;
898
899 if (uc_info == NULL)
900 return -EINVAL;
901
902 /* Re-route all voice usecases on the shared backend other than the
903 specified usecase to new snd devices */
904 list_for_each(node, &adev->usecase_list) {
905 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800906 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530907 enable_audio_route(adev, usecase);
908 }
909 return 0;
910}
911
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530912static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530913{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530914 ALOGV("%s", __func__);
915 audio_route_apply_and_update_path(adev->audio_route,
916 "asrc-mode");
917 adev->asrc_mode_enabled = true;
918}
919
920static void disable_asrc_mode(struct audio_device *adev)
921{
922 ALOGV("%s", __func__);
923 audio_route_reset_and_update_path(adev->audio_route,
924 "asrc-mode");
925 adev->asrc_mode_enabled = false;
926}
927
928/*
929 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
930 * 44.1 or Native DSD backends are enabled for any of current use case.
931 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
932 * - Disable current mix path use case(Headphone backend) and re-enable it with
933 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
934 * e.g. Naitve DSD or Headphone 44.1 -> + 48
935 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530936static void check_and_set_asrc_mode(struct audio_device *adev,
937 struct audio_usecase *uc_info,
938 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530939{
940 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530941 int i, num_new_devices = 0;
942 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
943 /*
944 *Split snd device for new combo use case
945 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
946 */
947 if (platform_split_snd_device(adev->platform,
948 snd_device,
949 &num_new_devices,
950 split_new_snd_devices) == 0) {
951 for (i = 0; i < num_new_devices; i++)
952 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
953 } else {
954 int new_backend_idx = platform_get_backend_index(snd_device);
955 if (((new_backend_idx == HEADPHONE_BACKEND) ||
956 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
957 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
958 !adev->asrc_mode_enabled) {
959 struct listnode *node = NULL;
960 struct audio_usecase *uc = NULL;
961 struct stream_out *curr_out = NULL;
962 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
963 int i, num_devices, ret = 0;
964 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530965
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530966 list_for_each(node, &adev->usecase_list) {
967 uc = node_to_item(node, struct audio_usecase, list);
968 curr_out = (struct stream_out*) uc->stream.out;
969 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
970 /*
971 *Split snd device for existing combo use case
972 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
973 */
974 ret = platform_split_snd_device(adev->platform,
975 uc->out_snd_device,
976 &num_devices,
977 split_snd_devices);
978 if (ret < 0 || num_devices == 0) {
979 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
980 split_snd_devices[0] = uc->out_snd_device;
981 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800982 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530983 for (i = 0; i < num_devices; i++) {
984 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
985 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
986 if((new_backend_idx == HEADPHONE_BACKEND) &&
987 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
988 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
989 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
990 __func__);
991 enable_asrc_mode(adev);
992 break;
993 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
994 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
995 (usecase_backend_idx == HEADPHONE_BACKEND)) {
996 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
997 __func__);
998 disable_audio_route(adev, uc);
999 disable_snd_device(adev, uc->out_snd_device);
1000 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
1001 if (new_backend_idx == DSD_NATIVE_BACKEND)
1002 audio_route_apply_and_update_path(adev->audio_route,
1003 "hph-true-highquality-mode");
1004 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1005 (curr_out->bit_width >= 24))
1006 audio_route_apply_and_update_path(adev->audio_route,
1007 "hph-highquality-mode");
1008 enable_asrc_mode(adev);
1009 enable_snd_device(adev, uc->out_snd_device);
1010 enable_audio_route(adev, uc);
1011 break;
1012 }
1013 }
1014 // reset split devices count
1015 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001016 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301017 if (adev->asrc_mode_enabled)
1018 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301019 }
1020 }
1021 }
1022}
1023
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001024static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1025 struct audio_effect_config effect_config,
1026 unsigned int param_value)
1027{
1028 char mixer_ctl_name[] = "Audio Effect";
1029 struct mixer_ctl *ctl;
1030 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001031 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001032
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001033 if (in == NULL) {
1034 ALOGE("%s: active input stream is NULL", __func__);
1035 return -EINVAL;
1036 }
1037
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001038 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1039 if (!ctl) {
1040 ALOGE("%s: Could not get mixer ctl - %s",
1041 __func__, mixer_ctl_name);
1042 return -EINVAL;
1043 }
1044
1045 set_values[0] = 1; //0:Rx 1:Tx
1046 set_values[1] = in->app_type_cfg.app_type;
1047 set_values[2] = (long)effect_config.module_id;
1048 set_values[3] = (long)effect_config.instance_id;
1049 set_values[4] = (long)effect_config.param_id;
1050 set_values[5] = param_value;
1051
1052 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1053
1054 return 0;
1055
1056}
1057
1058static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1059 int effect_type, unsigned int *param_value)
1060{
1061 int ret = 0;
1062 struct audio_effect_config other_effect_config;
1063 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001064 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001065
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001066 if (in == NULL) {
1067 ALOGE("%s: active input stream is NULL", __func__);
1068 return -EINVAL;
1069 }
1070
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001071 usecase = get_usecase_from_list(adev, in->usecase);
1072 if (!usecase)
1073 return -EINVAL;
1074
1075 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1076 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1077 if (ret < 0) {
1078 ALOGE("%s Failed to get effect params %d", __func__, ret);
1079 return ret;
1080 }
1081
1082 if (module_id == other_effect_config.module_id) {
1083 //Same module id for AEC/NS. Values need to be combined
1084 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1085 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1086 *param_value |= other_effect_config.param_value;
1087 }
1088 }
1089
1090 return ret;
1091}
1092
1093static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301094{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001095 struct audio_effect_config effect_config;
1096 struct audio_usecase *usecase = NULL;
1097 int ret = 0;
1098 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001099 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001100
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001101 if(!voice_extn_is_dynamic_ecns_enabled())
1102 return ENOSYS;
1103
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001104 if (!in) {
1105 ALOGE("%s: Invalid input stream", __func__);
1106 return -EINVAL;
1107 }
1108
1109 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1110
1111 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001112 if (usecase == NULL) {
1113 ALOGE("%s: Could not find the usecase (%d) in the list",
1114 __func__, in->usecase);
1115 return -EINVAL;
1116 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001117
1118 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1119 if (ret < 0) {
1120 ALOGE("%s Failed to get module id %d", __func__, ret);
1121 return ret;
1122 }
1123 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1124 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1125
1126 if(enable)
1127 param_value = effect_config.param_value;
1128
1129 /*Special handling for AEC & NS effects Param values need to be
1130 updated if module ids are same*/
1131
1132 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1133 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1134 if (ret < 0)
1135 return ret;
1136 }
1137
1138 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1139
1140 return ret;
1141}
1142
1143static void check_and_enable_effect(struct audio_device *adev)
1144{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001145 if(!voice_extn_is_dynamic_ecns_enabled())
1146 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001147
Eric Laurent637e2d42018-11-15 12:24:31 -08001148 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001149
Eric Laurent637e2d42018-11-15 12:24:31 -08001150 if (in != NULL && !in->standby) {
1151 if (in->enable_aec)
1152 enable_disable_effect(adev, EFFECT_AEC, true);
1153
1154 if (in->enable_ns &&
1155 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1156 enable_disable_effect(adev, EFFECT_NS, true);
1157 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001158 }
1159}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001160
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001161int pcm_ioctl(struct pcm *pcm, int request, ...)
1162{
1163 va_list ap;
1164 void * arg;
1165 int pcm_fd = *(int*)pcm;
1166
1167 va_start(ap, request);
1168 arg = va_arg(ap, void *);
1169 va_end(ap);
1170
1171 return ioctl(pcm_fd, request, arg);
1172}
1173
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001174int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001175 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001176{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001177 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001178 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301179 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301180 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001181 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301182 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001183
1184 if (usecase == NULL)
1185 return -EINVAL;
1186
1187 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1188
Carter Hsu2e429db2019-05-14 18:50:52 +08001189 if (usecase->type == PCM_CAPTURE) {
1190 struct stream_in *in = usecase->stream.in;
1191 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001192 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001193
1194 if (in) {
1195 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001196 list_init(&out_devices);
1197 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001198 struct listnode *node;
1199 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1200 USECASE_AUDIO_PLAYBACK_VOIP);
1201 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001202 assign_devices(&out_devices,
1203 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001204 } else if (adev->primary_output &&
1205 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001206 assign_devices(&out_devices,
1207 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001208 } else {
1209 list_for_each(node, &adev->usecase_list) {
1210 uinfo = node_to_item(node, struct audio_usecase, list);
1211 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001212 assign_devices(&out_devices,
1213 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001214 break;
1215 }
1216 }
1217 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001218
1219 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001220 in->ec_opened = true;
1221 }
1222 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001223 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1224 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1225 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001226 snd_device = usecase->in_snd_device;
1227 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001228 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001229 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001230
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001231#ifdef DS1_DOLBY_DAP_ENABLED
1232 audio_extn_dolby_set_dmid(adev);
1233 audio_extn_dolby_set_endpoint(adev);
1234#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001235 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001236 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301237 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001238 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001239 if (audio_extn_is_maxx_audio_enabled())
1240 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301241 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301242 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1243 out = usecase->stream.out;
1244 if (out && out->compr)
1245 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1246 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301247
1248 if (usecase->type == PCM_CAPTURE) {
1249 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001250 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301251 ALOGD("%s: set custom mtmx params v1", __func__);
1252 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1253 }
1254 } else {
1255 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1256 }
Manish Dewangan58229382017-02-02 15:48:41 +05301257
Andy Hung756ecc12018-10-19 17:47:12 -07001258 // we shouldn't truncate mixer_path
1259 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1260 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1261 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001262 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001263 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301264 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1265 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1266 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1267 if (parms) {
1268 audio_extn_fm_set_parameters(adev, parms);
1269 str_parms_destroy(parms);
1270 }
1271 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272 ALOGV("%s: exit", __func__);
1273 return 0;
1274}
1275
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001276int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001277 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001279 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001280 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301281 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001282
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301283 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001284 return -EINVAL;
1285
1286 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301287 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001288 snd_device = usecase->in_snd_device;
1289 else
1290 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001291 // we shouldn't truncate mixer_path
1292 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1293 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1294 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001295 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001296 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001297 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001298 if (usecase->type == PCM_CAPTURE) {
1299 struct stream_in *in = usecase->stream.in;
1300 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001301 struct listnode out_devices;
1302 list_init(&out_devices);
1303 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001304 in->ec_opened = false;
1305 }
1306 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001307 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301308 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301309
1310 if (usecase->type == PCM_CAPTURE) {
1311 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001312 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301313 ALOGD("%s: reset custom mtmx params v1", __func__);
1314 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1315 }
1316 } else {
1317 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1318 }
1319
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001320 if ((usecase->type == PCM_PLAYBACK) &&
1321 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301322 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001324 ALOGV("%s: exit", __func__);
1325 return 0;
1326}
1327
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001328int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001329 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001330{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301331 int i, num_devices = 0;
1332 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001333 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1334
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001335 if (snd_device < SND_DEVICE_MIN ||
1336 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001337 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001338 return -EINVAL;
1339 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001340
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001341 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001342 ALOGE("%s: Invalid sound device returned", __func__);
1343 return -EINVAL;
1344 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001345
1346 adev->snd_dev_ref_cnt[snd_device]++;
1347
1348 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1349 (platform_split_snd_device(adev->platform,
1350 snd_device,
1351 &num_devices,
1352 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001353 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001354 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001355 return 0;
1356 }
1357
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001358 if (audio_extn_spkr_prot_is_enabled())
1359 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001360
Aalique Grahame22e49102018-12-18 14:23:57 -08001361 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1362
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001363 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1364 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001365 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1366 goto err;
1367 }
1368 audio_extn_dev_arbi_acquire(snd_device);
1369 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001370 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001371 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001372 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001373 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001374 } else if (platform_split_snd_device(adev->platform,
1375 snd_device,
1376 &num_devices,
1377 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301378 for (i = 0; i < num_devices; i++) {
1379 enable_snd_device(adev, new_snd_devices[i]);
1380 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001381 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001382 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001383 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301384
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301385
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001386 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1387 (audio_extn_a2dp_start_playback() < 0)) {
1388 ALOGE(" fail to configure A2dp Source control path ");
1389 goto err;
1390 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001391
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001392 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1393 (audio_extn_a2dp_start_capture() < 0)) {
1394 ALOGE(" fail to configure A2dp Sink control path ");
1395 goto err;
1396 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301397
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001398 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1399 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1400 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1401 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1402 ALOGE(" fail to configure sco control path ");
1403 goto err;
1404 }
Zhou Song12c29502019-03-16 10:37:18 +08001405 }
1406
Zhou Song331c8e52019-08-26 14:16:12 +08001407 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001408 /* due to the possibility of calibration overwrite between listen
1409 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001410 audio_extn_sound_trigger_update_device_status(snd_device,
1411 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301412 audio_extn_listen_update_device_status(snd_device,
1413 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001414 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001415 audio_extn_sound_trigger_update_device_status(snd_device,
1416 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301417 audio_extn_listen_update_device_status(snd_device,
1418 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001419 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001420 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001421 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001422 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301423
1424 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1425 !adev->native_playback_enabled &&
1426 audio_is_true_native_stream_active(adev)) {
1427 ALOGD("%s: %d: napb: enabling native mode in hardware",
1428 __func__, __LINE__);
1429 audio_route_apply_and_update_path(adev->audio_route,
1430 "true-native-mode");
1431 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301432 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301433 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1434 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001435 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001436 ALOGD("%s: init ec ref loopback", __func__);
1437 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1438 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001439 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001440 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001441err:
1442 adev->snd_dev_ref_cnt[snd_device]--;
1443 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001444}
1445
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001446int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001447 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001448{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301449 int i, num_devices = 0;
1450 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001451 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1452
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001453 if (snd_device < SND_DEVICE_MIN ||
1454 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001455 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001456 return -EINVAL;
1457 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001458
1459 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1460 ALOGE("%s: Invalid sound device returned", __func__);
1461 return -EINVAL;
1462 }
1463
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001464 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1465 ALOGE("%s: device ref cnt is already 0", __func__);
1466 return -EINVAL;
1467 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001468
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001469 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001470
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001471
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001472 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001473 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301474
Aalique Grahame22e49102018-12-18 14:23:57 -08001475 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1476
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001477 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1478 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001479 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001480
1481 // when speaker device is disabled, reset swap.
1482 // will be renabled on usecase start
1483 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001484 } else if (platform_split_snd_device(adev->platform,
1485 snd_device,
1486 &num_devices,
1487 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301488 for (i = 0; i < num_devices; i++) {
1489 disable_snd_device(adev, new_snd_devices[i]);
1490 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001491 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001492 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001493 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001494 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001495
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001496 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301497 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001498 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001499 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001500 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001501 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301502 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001503 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301504 adev->native_playback_enabled) {
1505 ALOGD("%s: %d: napb: disabling native mode in hardware",
1506 __func__, __LINE__);
1507 audio_route_reset_and_update_path(adev->audio_route,
1508 "true-native-mode");
1509 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001510 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301511 adev->asrc_mode_enabled) {
1512 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301513 disable_asrc_mode(adev);
1514 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001515 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301516 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001517 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001518 ALOGD("%s: deinit ec ref loopback", __func__);
1519 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1520 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001521
1522 audio_extn_utils_release_snd_device(snd_device);
1523 } else {
1524 if (platform_split_snd_device(adev->platform,
1525 snd_device,
1526 &num_devices,
1527 new_snd_devices) == 0) {
1528 for (i = 0; i < num_devices; i++) {
1529 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1530 }
1531 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001532 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 return 0;
1535}
1536
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001537/*
1538 legend:
1539 uc - existing usecase
1540 new_uc - new usecase
1541 d1, d11, d2 - SND_DEVICE enums
1542 a1, a2 - corresponding ANDROID device enums
1543 B1, B2 - backend strings
1544
1545case 1
1546 uc->dev d1 (a1) B1
1547 new_uc->dev d1 (a1), d2 (a2) B1, B2
1548
1549 resolution: disable and enable uc->dev on d1
1550
1551case 2
1552 uc->dev d1 (a1) B1
1553 new_uc->dev d11 (a1) B1
1554
1555 resolution: need to switch uc since d1 and d11 are related
1556 (e.g. speaker and voice-speaker)
1557 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1558
1559case 3
1560 uc->dev d1 (a1) B1
1561 new_uc->dev d2 (a2) B2
1562
1563 resolution: no need to switch uc
1564
1565case 4
1566 uc->dev d1 (a1) B1
1567 new_uc->dev d2 (a2) B1
1568
1569 resolution: disable enable uc-dev on d2 since backends match
1570 we cannot enable two streams on two different devices if they
1571 share the same backend. e.g. if offload is on speaker device using
1572 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1573 using the same backend, offload must also be switched to voice-handset.
1574
1575case 5
1576 uc->dev d1 (a1) B1
1577 new_uc->dev d1 (a1), d2 (a2) B1
1578
1579 resolution: disable enable uc-dev on d2 since backends match
1580 we cannot enable two streams on two different devices if they
1581 share the same backend.
1582
1583case 6
1584 uc->dev d1 (a1) B1
1585 new_uc->dev d2 (a1) B2
1586
1587 resolution: no need to switch
1588
1589case 7
1590 uc->dev d1 (a1), d2 (a2) B1, B2
1591 new_uc->dev d1 (a1) B1
1592
1593 resolution: no need to switch
1594
Zhou Song4ba65882018-07-09 14:48:07 +08001595case 8
1596 uc->dev d1 (a1) B1
1597 new_uc->dev d11 (a1), d2 (a2) B1, B2
1598 resolution: compared to case 1, for this case, d1 and d11 are related
1599 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001600*/
1601static snd_device_t derive_playback_snd_device(void * platform,
1602 struct audio_usecase *uc,
1603 struct audio_usecase *new_uc,
1604 snd_device_t new_snd_device)
1605{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001606 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001607
1608 snd_device_t d1 = uc->out_snd_device;
1609 snd_device_t d2 = new_snd_device;
1610
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001611 list_init(&a1);
1612 list_init(&a2);
1613
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301614 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301615 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001616 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1617 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301618 break;
1619 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001620 assign_devices(&a1, &uc->stream.out->device_list);
1621 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301622 break;
1623 }
1624
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001625 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001626 if (!compare_devices(&a1, &a2) &&
1627 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001628 snd_device_t d3[2];
1629 int num_devices = 0;
1630 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001631 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001632 &num_devices,
1633 d3);
1634 if (ret < 0) {
1635 if (ret != -ENOSYS) {
1636 ALOGW("%s failed to split snd_device %d",
1637 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001638 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001639 }
1640 goto end;
1641 }
1642
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001643 if (platform_check_backends_match(d3[0], d3[1])) {
1644 return d2; // case 5
1645 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001646 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301647 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001648 // check if d1 is related to any of d3's
1649 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001650 return d1; // case 1
1651 else
1652 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001653 }
1654 } else {
1655 if (platform_check_backends_match(d1, d2)) {
1656 return d2; // case 2, 4
1657 } else {
1658 return d1; // case 6, 3
1659 }
1660 }
1661
1662end:
1663 return d2; // return whatever was calculated before.
1664}
1665
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001666static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301667 struct audio_usecase *uc_info,
1668 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001669{
1670 struct listnode *node;
1671 struct audio_usecase *usecase;
1672 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301673 snd_device_t uc_derive_snd_device;
1674 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001675 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1676 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001677 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301678 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001679 /*
1680 * This function is to make sure that all the usecases that are active on
1681 * the hardware codec backend are always routed to any one device that is
1682 * handled by the hardware codec.
1683 * For example, if low-latency and deep-buffer usecases are currently active
1684 * on speaker and out_set_parameters(headset) is received on low-latency
1685 * output, then we have to make sure deep-buffer is also switched to headset,
1686 * because of the limitation that both the devices cannot be enabled
1687 * at the same time as they share the same backend.
1688 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001689 /*
1690 * This call is to check if we need to force routing for a particular stream
1691 * If there is a backend configuration change for the device when a
1692 * new stream starts, then ADM needs to be closed and re-opened with the new
1693 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001694 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001695 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001696 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1697 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301698 /* For a2dp device reconfigure all active sessions
1699 * with new AFE encoder format based on a2dp state
1700 */
1701 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1702 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1703 audio_extn_a2dp_is_force_device_switch()) {
1704 force_routing = true;
1705 force_restart_session = true;
1706 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301707 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1708
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001709 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001710 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001711 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1713 switch_device[i] = false;
1714
1715 list_for_each(node, &adev->usecase_list) {
1716 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001717
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301718 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1719 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301720 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301721 platform_get_snd_device_name(usecase->out_snd_device),
1722 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301723 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1724 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301725 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1726 usecase, uc_info, snd_device);
1727 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001728 (is_codec_backend_out_device_type(&usecase->device_list) ||
1729 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1730 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1731 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1732 is_a2dp_out_device_type(&usecase->device_list) ||
1733 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301734 ((force_restart_session) ||
1735 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301736 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1737 __func__, use_case_table[usecase->id],
1738 platform_get_snd_device_name(usecase->out_snd_device));
1739 disable_audio_route(adev, usecase);
1740 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301741 /* Enable existing usecase on derived playback device */
1742 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301743 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301744 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001745 }
1746 }
1747
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301748 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1749 num_uc_to_switch);
1750
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001751 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001752 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001753
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301754 /* Make sure the previous devices to be disabled first and then enable the
1755 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001756 list_for_each(node, &adev->usecase_list) {
1757 usecase = node_to_item(node, struct audio_usecase, list);
1758 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001759 /* Check if output sound device to be switched can be split and if any
1760 of the split devices match with derived sound device */
1761 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1762 &num_devices, split_snd_devices) == 0) {
1763 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1764 for (i = 0; i < num_devices; i++) {
1765 /* Disable devices that do not match with derived sound device */
1766 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1767 disable_snd_device(adev, split_snd_devices[i]);
1768 }
1769 } else {
1770 disable_snd_device(adev, usecase->out_snd_device);
1771 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001772 }
1773 }
1774
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001775 list_for_each(node, &adev->usecase_list) {
1776 usecase = node_to_item(node, struct audio_usecase, list);
1777 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001778 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1779 &num_devices, split_snd_devices) == 0) {
1780 /* Enable derived sound device only if it does not match with
1781 one of the split sound devices. This is because the matching
1782 sound device was not disabled */
1783 bool should_enable = true;
1784 for (i = 0; i < num_devices; i++) {
1785 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1786 should_enable = false;
1787 break;
1788 }
1789 }
1790 if (should_enable)
1791 enable_snd_device(adev, derive_snd_device[usecase->id]);
1792 } else {
1793 enable_snd_device(adev, derive_snd_device[usecase->id]);
1794 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001795 }
1796 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001797
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001798 /* Re-route all the usecases on the shared backend other than the
1799 specified usecase to new snd devices */
1800 list_for_each(node, &adev->usecase_list) {
1801 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301802 /* Update the out_snd_device only before enabling the audio route */
1803 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301804 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301805 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301806 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301807 use_case_table[usecase->id],
1808 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001809 /* Update voc calibration before enabling VoIP route */
1810 if (usecase->type == VOIP_CALL)
1811 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001812 usecase->out_snd_device,
1813 platform_get_input_snd_device(
1814 adev->platform, NULL,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001815 &uc_info->device_list));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301816 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301817 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001818 out_set_voip_volume(&usecase->stream.out->stream,
1819 usecase->stream.out->volume_l,
1820 usecase->stream.out->volume_r);
1821 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301822 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001823 }
1824 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001825 }
1826}
1827
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301828static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001829 struct audio_usecase *uc_info,
1830 snd_device_t snd_device)
1831{
1832 struct listnode *node;
1833 struct audio_usecase *usecase;
1834 bool switch_device[AUDIO_USECASE_MAX];
1835 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001836 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001837 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001838
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301839 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1840 snd_device);
1841 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301842
1843 /*
1844 * Make sure out devices is checked against out codec backend device and
1845 * also in devices against in codec backend. Checking out device against in
1846 * codec backend or vice versa causes issues.
1847 */
1848 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001849 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001850 /*
1851 * This function is to make sure that all the active capture usecases
1852 * are always routed to the same input sound device.
1853 * For example, if audio-record and voice-call usecases are currently
1854 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1855 * is received for voice call then we have to make sure that audio-record
1856 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1857 * because of the limitation that two devices cannot be enabled
1858 * at the same time if they share the same backend.
1859 */
1860 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1861 switch_device[i] = false;
1862
1863 list_for_each(node, &adev->usecase_list) {
1864 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301865 /*
1866 * TODO: Enhance below condition to handle BT sco/USB multi recording
1867 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001868 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001869 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301870 (usecase->in_snd_device != snd_device || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001871 ((backend_check_cond &&
1872 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001873 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001874 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001875 is_single_device_type_equal(&usecase->device_list,
1876 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001877 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001878 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001879 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001880 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1881 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001882 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001883 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001884 switch_device[usecase->id] = true;
1885 num_uc_to_switch++;
1886 }
1887 }
1888
1889 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001890 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001891
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301892 /* Make sure the previous devices to be disabled first and then enable the
1893 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001894 list_for_each(node, &adev->usecase_list) {
1895 usecase = node_to_item(node, struct audio_usecase, list);
1896 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001897 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001898 }
1899 }
1900
1901 list_for_each(node, &adev->usecase_list) {
1902 usecase = node_to_item(node, struct audio_usecase, list);
1903 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001904 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001905 }
1906 }
1907
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001908 /* Re-route all the usecases on the shared backend other than the
1909 specified usecase to new snd devices */
1910 list_for_each(node, &adev->usecase_list) {
1911 usecase = node_to_item(node, struct audio_usecase, list);
1912 /* Update the in_snd_device only before enabling the audio route */
1913 if (switch_device[usecase->id] ) {
1914 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001915 if (usecase->type != VOICE_CALL) {
1916 /* Update voc calibration before enabling VoIP route */
1917 if (usecase->type == VOIP_CALL)
1918 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001919 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001920 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301921 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001922 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001923 }
1924 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001925 }
1926}
1927
Mingming Yin3a941d42016-02-17 18:08:05 -08001928static void reset_hdmi_sink_caps(struct stream_out *out) {
1929 int i = 0;
1930
1931 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1932 out->supported_channel_masks[i] = 0;
1933 }
1934 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1935 out->supported_formats[i] = 0;
1936 }
1937 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1938 out->supported_sample_rates[i] = 0;
1939 }
1940}
1941
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001943static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001944{
Mingming Yin3a941d42016-02-17 18:08:05 -08001945 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001946 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
1947 out->extconn.cs.controller,
1948 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949
Mingming Yin3a941d42016-02-17 18:08:05 -08001950 reset_hdmi_sink_caps(out);
1951
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001952 /* Cache ext disp type */
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001953 if (platform_get_ext_disp_type_v2(adev->platform,
1954 out->extconn.cs.controller,
1955 out->extconn.cs.stream <= 0)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001956 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001957 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001958 }
1959
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001962 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001963 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001964 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1965 case 6:
1966 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1967 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1968 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1969 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1970 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1971 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972 break;
1973 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001974 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001975 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976 break;
1977 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001978
1979 // check channel format caps
1980 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001981 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
1982 out->extconn.cs.controller,
1983 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08001984 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1985 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1986 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1987 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1988 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1989 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1990 }
1991
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001992 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
1993 out->extconn.cs.controller,
1994 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07001995 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1996 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1997 }
1998
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001999 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2000 out->extconn.cs.controller,
2001 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002002 ALOGV(":%s HDMI supports DTS format", __func__);
2003 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2004 }
2005
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002006 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2007 out->extconn.cs.controller,
2008 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002009 ALOGV(":%s HDMI supports DTS HD format", __func__);
2010 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2011 }
2012
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002013 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2014 out->extconn.cs.controller,
2015 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002016 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2017 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2018 }
2019
Mingming Yin3a941d42016-02-17 18:08:05 -08002020
2021 // check sample rate caps
2022 i = 0;
2023 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002024 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2025 out->extconn.cs.controller,
2026 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002027 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2028 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2029 }
2030 }
2031
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002032 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033}
2034
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002035static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2036 uint32_t *supported_sample_rates __unused,
2037 uint32_t max_rates __unused)
2038{
2039 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2040 supported_sample_rates,
2041 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302042 ssize_t i = 0;
2043
2044 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002045 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2046 supported_sample_rates[i]);
2047 }
2048 return count;
2049}
2050
2051static inline int read_usb_sup_channel_masks(bool is_playback,
2052 audio_channel_mask_t *supported_channel_masks,
2053 uint32_t max_masks)
2054{
2055 int channels = audio_extn_usb_get_max_channels(is_playback);
2056 int channel_count;
2057 uint32_t num_masks = 0;
2058 if (channels > MAX_HIFI_CHANNEL_COUNT)
2059 channels = MAX_HIFI_CHANNEL_COUNT;
2060
2061 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002062 // start from 2 channels as framework currently doesn't support mono.
2063 if (channels >= FCC_2) {
2064 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2065 }
2066 for (channel_count = FCC_2;
2067 channel_count <= channels && num_masks < max_masks;
2068 ++channel_count) {
2069 supported_channel_masks[num_masks++] =
2070 audio_channel_mask_for_index_assignment_from_count(channel_count);
2071 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002072 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002073 // For capture we report all supported channel masks from 1 channel up.
2074 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002075 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2076 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002077 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2078 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2079 if (channel_count <= FCC_2) {
2080 mask = audio_channel_in_mask_from_count(channel_count);
2081 supported_channel_masks[num_masks++] = mask;
2082 }
2083 const audio_channel_mask_t index_mask =
2084 audio_channel_mask_for_index_assignment_from_count(channel_count);
2085 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2086 supported_channel_masks[num_masks++] = index_mask;
2087 }
2088 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002089 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302090
vincenttewf51c94e2019-05-07 10:28:53 +08002091 for (size_t i = 0; i < num_masks; ++i) {
2092 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2093 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302094 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002095 return num_masks;
2096}
2097
2098static inline int read_usb_sup_formats(bool is_playback __unused,
2099 audio_format_t *supported_formats,
2100 uint32_t max_formats __unused)
2101{
2102 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2103 switch (bitwidth) {
2104 case 24:
2105 // XXX : usb.c returns 24 for s24 and s24_le?
2106 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2107 break;
2108 case 32:
2109 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2110 break;
2111 case 16:
2112 default :
2113 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2114 break;
2115 }
2116 ALOGV("%s: %s supported format %d", __func__,
2117 is_playback ? "P" : "C", bitwidth);
2118 return 1;
2119}
2120
2121static inline int read_usb_sup_params_and_compare(bool is_playback,
2122 audio_format_t *format,
2123 audio_format_t *supported_formats,
2124 uint32_t max_formats,
2125 audio_channel_mask_t *mask,
2126 audio_channel_mask_t *supported_channel_masks,
2127 uint32_t max_masks,
2128 uint32_t *rate,
2129 uint32_t *supported_sample_rates,
2130 uint32_t max_rates) {
2131 int ret = 0;
2132 int num_formats;
2133 int num_masks;
2134 int num_rates;
2135 int i;
2136
2137 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2138 max_formats);
2139 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2140 max_masks);
2141
2142 num_rates = read_usb_sup_sample_rates(is_playback,
2143 supported_sample_rates, max_rates);
2144
2145#define LUT(table, len, what, dflt) \
2146 for (i=0; i<len && (table[i] != what); i++); \
2147 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2148
2149 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2150 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2151 LUT(supported_sample_rates, num_rates, *rate, 0);
2152
2153#undef LUT
2154 return ret < 0 ? -EINVAL : 0; // HACK TBD
2155}
2156
Alexy Josephb1379942016-01-29 15:49:38 -08002157audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002158 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002159{
2160 struct audio_usecase *usecase;
2161 struct listnode *node;
2162
2163 list_for_each(node, &adev->usecase_list) {
2164 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002165 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002166 ALOGV("%s: usecase id %d", __func__, usecase->id);
2167 return usecase->id;
2168 }
2169 }
2170 return USECASE_INVALID;
2171}
2172
Alexy Josephb1379942016-01-29 15:49:38 -08002173struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002174 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002175{
2176 struct audio_usecase *usecase;
2177 struct listnode *node;
2178
2179 list_for_each(node, &adev->usecase_list) {
2180 usecase = node_to_item(node, struct audio_usecase, list);
2181 if (usecase->id == uc_id)
2182 return usecase;
2183 }
2184 return NULL;
2185}
2186
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302187/*
2188 * is a true native playback active
2189 */
2190bool audio_is_true_native_stream_active(struct audio_device *adev)
2191{
2192 bool active = false;
2193 int i = 0;
2194 struct listnode *node;
2195
2196 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2197 ALOGV("%s:napb: not in true mode or non hdphones device",
2198 __func__);
2199 active = false;
2200 goto exit;
2201 }
2202
2203 list_for_each(node, &adev->usecase_list) {
2204 struct audio_usecase *uc;
2205 uc = node_to_item(node, struct audio_usecase, list);
2206 struct stream_out *curr_out =
2207 (struct stream_out*) uc->stream.out;
2208
2209 if (curr_out && PCM_PLAYBACK == uc->type) {
2210 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2211 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2212 uc->id, curr_out->sample_rate,
2213 curr_out->bit_width,
2214 platform_get_snd_device_name(uc->out_snd_device));
2215
2216 if (is_offload_usecase(uc->id) &&
2217 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2218 active = true;
2219 ALOGD("%s:napb:native stream detected", __func__);
2220 }
2221 }
2222 }
2223exit:
2224 return active;
2225}
2226
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002227uint32_t adev_get_dsp_bit_width_enforce_mode()
2228{
2229 if (adev == NULL) {
2230 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2231 return 0;
2232 }
2233 return adev->dsp_bit_width_enforce_mode;
2234}
2235
2236static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2237{
2238 char value[PROPERTY_VALUE_MAX];
2239 int trial;
2240 uint32_t dsp_bit_width_enforce_mode = 0;
2241
2242 if (!mixer) {
2243 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2244 __func__);
2245 return 0;
2246 }
2247
2248 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2249 value, NULL) > 0) {
2250 trial = atoi(value);
2251 switch (trial) {
2252 case 16:
2253 dsp_bit_width_enforce_mode = 16;
2254 break;
2255 case 24:
2256 dsp_bit_width_enforce_mode = 24;
2257 break;
2258 case 32:
2259 dsp_bit_width_enforce_mode = 32;
2260 break;
2261 default:
2262 dsp_bit_width_enforce_mode = 0;
2263 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2264 break;
2265 }
2266 }
2267
2268 return dsp_bit_width_enforce_mode;
2269}
2270
2271static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2272 uint32_t enforce_mode,
2273 bool enable)
2274{
2275 struct mixer_ctl *ctl = NULL;
2276 const char *mixer_ctl_name = "ASM Bit Width";
2277 uint32_t asm_bit_width_mode = 0;
2278
2279 if (enforce_mode == 0) {
2280 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2281 return;
2282 }
2283
2284 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2285 if (!ctl) {
2286 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2287 __func__, mixer_ctl_name);
2288 return;
2289 }
2290
2291 if (enable)
2292 asm_bit_width_mode = enforce_mode;
2293 else
2294 asm_bit_width_mode = 0;
2295
2296 ALOGV("%s DSP bit width feature status is %d width=%d",
2297 __func__, enable, asm_bit_width_mode);
2298 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2299 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2300 asm_bit_width_mode);
2301
2302 return;
2303}
2304
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302305/*
2306 * if native DSD playback active
2307 */
2308bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2309{
2310 bool active = false;
2311 struct listnode *node = NULL;
2312 struct audio_usecase *uc = NULL;
2313 struct stream_out *curr_out = NULL;
2314
2315 list_for_each(node, &adev->usecase_list) {
2316 uc = node_to_item(node, struct audio_usecase, list);
2317 curr_out = (struct stream_out*) uc->stream.out;
2318
2319 if (curr_out && PCM_PLAYBACK == uc->type &&
2320 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2321 active = true;
2322 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302323 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302324 }
2325 }
2326 return active;
2327}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302328
2329static bool force_device_switch(struct audio_usecase *usecase)
2330{
2331 bool ret = false;
2332 bool is_it_true_mode = false;
2333
Zhou Song30f2c3e2018-02-08 14:02:15 +08002334 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302335 usecase->type == TRANSCODE_LOOPBACK_RX ||
2336 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002337 return false;
2338 }
2339
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002340 if(usecase->stream.out == NULL) {
2341 ALOGE("%s: stream.out is NULL", __func__);
2342 return false;
2343 }
2344
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302345 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002346 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002347 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2348 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302349 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2350 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2351 (!is_it_true_mode && adev->native_playback_enabled)){
2352 ret = true;
2353 ALOGD("napb: time to toggle native mode");
2354 }
2355 }
2356
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302357 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302358 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2359 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002360 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302361 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302362 ALOGD("Force a2dp device switch to update new encoder config");
2363 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002364 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302365
Florian Pfister1a84f312018-07-19 14:38:18 +02002366 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302367 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2368 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002369 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302370 return ret;
2371}
2372
Aalique Grahame22e49102018-12-18 14:23:57 -08002373static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2374{
2375 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2376}
2377
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302378bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2379{
2380 bool ret=false;
2381 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002382 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2383 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302384 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2385 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002386 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302387 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2388 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2389 ret = true;
2390
2391 return ret;
2392}
2393
2394bool is_a2dp_device(snd_device_t out_snd_device)
2395{
2396 bool ret=false;
2397 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2398 ret = true;
2399
2400 return ret;
2401}
2402
2403bool is_bt_soc_on(struct audio_device *adev)
2404{
2405 struct mixer_ctl *ctl;
2406 char *mixer_ctl_name = "BT SOC status";
2407 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2408 bool bt_soc_status = true;
2409 if (!ctl) {
2410 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2411 __func__, mixer_ctl_name);
2412 /*This is to ensure we dont break targets which dont have the kernel change*/
2413 return true;
2414 }
2415 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2416 ALOGD("BT SOC status: %d",bt_soc_status);
2417 return bt_soc_status;
2418}
2419
Zhou Song331c8e52019-08-26 14:16:12 +08002420static int configure_btsco_sample_rate(snd_device_t snd_device)
2421{
2422 struct mixer_ctl *ctl = NULL;
2423 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2424 char *rate_str = NULL;
2425 bool is_rx_dev = true;
2426
2427 if (is_btsco_device(snd_device, snd_device)) {
2428 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2429 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2430 if (!ctl_sr_tx || !ctl_sr_rx) {
2431 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2432 if (!ctl_sr)
2433 return -ENOSYS;
2434 }
2435
2436 switch (snd_device) {
2437 case SND_DEVICE_OUT_BT_SCO:
2438 rate_str = "KHZ_8";
2439 break;
2440 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2441 case SND_DEVICE_IN_BT_SCO_MIC:
2442 rate_str = "KHZ_8";
2443 is_rx_dev = false;
2444 break;
2445 case SND_DEVICE_OUT_BT_SCO_WB:
2446 rate_str = "KHZ_16";
2447 break;
2448 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2449 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2450 rate_str = "KHZ_16";
2451 is_rx_dev = false;
2452 break;
2453 default:
2454 return 0;
2455 }
2456
2457 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2458 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2459 return -ENOSYS;
2460 }
2461 return 0;
2462}
2463
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302464int out_standby_l(struct audio_stream *stream);
2465
Eric Laurent637e2d42018-11-15 12:24:31 -08002466struct stream_in *adev_get_active_input(const struct audio_device *adev)
2467{
2468 struct listnode *node;
2469 struct stream_in *last_active_in = NULL;
2470
2471 /* Get last added active input.
2472 * TODO: We may use a priority mechanism to pick highest priority active source */
2473 list_for_each(node, &adev->usecase_list)
2474 {
2475 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2476 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2477 last_active_in = usecase->stream.in;
2478 }
2479
2480 return last_active_in;
2481}
2482
2483struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2484{
2485 struct listnode *node;
2486
2487 /* First check active inputs with voice communication source and then
2488 * any input if audio mode is in communication */
2489 list_for_each(node, &adev->usecase_list)
2490 {
2491 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2492 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2493 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2494 return usecase->stream.in;
2495 }
2496 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2497 return adev_get_active_input(adev);
2498
2499 return NULL;
2500}
2501
Carter Hsu2e429db2019-05-14 18:50:52 +08002502/*
2503 * Aligned with policy.h
2504 */
2505static inline int source_priority(int inputSource)
2506{
2507 switch (inputSource) {
2508 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2509 return 9;
2510 case AUDIO_SOURCE_CAMCORDER:
2511 return 8;
2512 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2513 return 7;
2514 case AUDIO_SOURCE_UNPROCESSED:
2515 return 6;
2516 case AUDIO_SOURCE_MIC:
2517 return 5;
2518 case AUDIO_SOURCE_ECHO_REFERENCE:
2519 return 4;
2520 case AUDIO_SOURCE_FM_TUNER:
2521 return 3;
2522 case AUDIO_SOURCE_VOICE_RECOGNITION:
2523 return 2;
2524 case AUDIO_SOURCE_HOTWORD:
2525 return 1;
2526 default:
2527 break;
2528 }
2529 return 0;
2530}
2531
2532static struct stream_in *get_priority_input(struct audio_device *adev)
2533{
2534 struct listnode *node;
2535 struct audio_usecase *usecase;
2536 int last_priority = 0, priority;
2537 struct stream_in *priority_in = NULL;
2538 struct stream_in *in;
2539
2540 list_for_each(node, &adev->usecase_list) {
2541 usecase = node_to_item(node, struct audio_usecase, list);
2542 if (usecase->type == PCM_CAPTURE) {
2543 in = usecase->stream.in;
2544 if (!in)
2545 continue;
2546 priority = source_priority(in->source);
2547
2548 if (priority > last_priority) {
2549 last_priority = priority;
2550 priority_in = in;
2551 }
2552 }
2553 }
2554 return priority_in;
2555}
2556
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002557int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002559 snd_device_t out_snd_device = SND_DEVICE_NONE;
2560 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002561 struct audio_usecase *usecase = NULL;
2562 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002563 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002564 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302565 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002566 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002567 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302569 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2570
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002571 usecase = get_usecase_from_list(adev, uc_id);
2572 if (usecase == NULL) {
2573 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2574 return -EINVAL;
2575 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002577 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002578 (usecase->type == VOIP_CALL) ||
2579 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302580 if(usecase->stream.out == NULL) {
2581 ALOGE("%s: stream.out is NULL", __func__);
2582 return -EINVAL;
2583 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002584 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002585 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2586 uc_id);
2587 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2588 uc_id);
2589 } else {
2590 out_snd_device = platform_get_output_snd_device(adev->platform,
2591 usecase->stream.out);
2592 in_snd_device = platform_get_input_snd_device(adev->platform,
2593 NULL,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002594 &usecase->stream.out->device_list);
Guodong Hu267bdf82019-08-12 19:22:32 +08002595 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002596 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302597 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302598 if (usecase->stream.inout == NULL) {
2599 ALOGE("%s: stream.inout is NULL", __func__);
2600 return -EINVAL;
2601 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002602 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302603 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2604 stream_out.format = usecase->stream.inout->out_config.format;
2605 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2606 out_snd_device = platform_get_output_snd_device(adev->platform,
2607 &stream_out);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002608 assign_devices(&usecase->device_list,
2609 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302610 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2611 if (usecase->stream.inout == NULL) {
2612 ALOGE("%s: stream.inout is NULL", __func__);
2613 return -EINVAL;
2614 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002615 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, NULL);
2616 assign_devices(&usecase->device_list,
2617 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002618 } else {
2619 /*
2620 * If the voice call is active, use the sound devices of voice call usecase
2621 * so that it would not result any device switch. All the usecases will
2622 * be switched to new device when select_devices() is called for voice call
2623 * usecase. This is to avoid switching devices for voice call when
2624 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002625 * choose voice call device only if the use case device is
2626 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002627 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002628 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002629 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002630 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002631 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2632 is_codec_backend_out_device_type(&usecase->device_list)) ||
2633 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2634 is_codec_backend_in_device_type(&usecase->device_list)) ||
2635 is_single_device_type_equal(&vc_usecase->device_list,
2636 AUDIO_DEVICE_OUT_HEARING_AID) ||
2637 is_single_device_type_equal(&usecase->device_list,
2638 AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002639 in_snd_device = vc_usecase->in_snd_device;
2640 out_snd_device = vc_usecase->out_snd_device;
2641 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002642 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002643 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002644 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002645 if ((voip_usecase != NULL) &&
2646 (usecase->type == PCM_PLAYBACK) &&
2647 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002648 out_snd_device_backend_match = platform_check_backends_match(
2649 voip_usecase->out_snd_device,
2650 platform_get_output_snd_device(
2651 adev->platform,
2652 usecase->stream.out));
2653 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002654 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2655 (is_codec_backend_out_device_type(&usecase->device_list) ||
2656 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002657 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002658 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002659 in_snd_device = voip_usecase->in_snd_device;
2660 out_snd_device = voip_usecase->out_snd_device;
2661 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002662 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002663 hfp_ucid = audio_extn_hfp_get_usecase();
2664 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002665 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002666 in_snd_device = hfp_usecase->in_snd_device;
2667 out_snd_device = hfp_usecase->out_snd_device;
2668 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002669 }
2670 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302671 if (usecase->stream.out == NULL) {
2672 ALOGE("%s: stream.out is NULL", __func__);
2673 return -EINVAL;
2674 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002675 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002676 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002677 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002678 struct stream_out *voip_out = adev->primary_output;
2679 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002680 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002681 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2682 else
2683 out_snd_device = platform_get_output_snd_device(adev->platform,
2684 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002685 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002686
Eric Laurent637e2d42018-11-15 12:24:31 -08002687 if (voip_usecase)
2688 voip_out = voip_usecase->stream.out;
2689
2690 if (usecase->stream.out == voip_out && voip_in != NULL)
2691 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002692 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002693 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302694 if (usecase->stream.in == NULL) {
2695 ALOGE("%s: stream.in is NULL", __func__);
2696 return -EINVAL;
2697 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002698 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002699 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002700 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002701 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002702 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002703 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002704
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002705 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002706 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002707 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2708 USECASE_AUDIO_PLAYBACK_VOIP);
2709
Carter Hsu2e429db2019-05-14 18:50:52 +08002710 usecase->stream.in->enable_ec_port = false;
2711
Zhou Song62ea0282020-03-22 19:53:01 +08002712 bool is_ha_usecase = adev->ha_proxy_enable ?
2713 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY2 :
2714 usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY;
2715 if (is_ha_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002716 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002717 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002718 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002719 } else if (adev->primary_output &&
2720 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002721 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002722 } else {
2723 /* forcing speaker o/p device to get matching i/p pair
2724 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002725 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002726 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002727 priority_in = voip_in;
2728 } else {
2729 /* get the input with the highest priority source*/
2730 priority_in = get_priority_input(adev);
2731
2732 if (!priority_in)
2733 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002734 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002735
Eric Laurent637e2d42018-11-15 12:24:31 -08002736 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002737 priority_in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002738 &out_devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002739 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002740 }
2741 }
2742
2743 if (out_snd_device == usecase->out_snd_device &&
2744 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302745
2746 if (!force_device_switch(usecase))
2747 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 }
2749
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002750 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002751 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002752 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002753 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2754 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302755 }
2756
Aalique Grahame22e49102018-12-18 14:23:57 -08002757 if (out_snd_device != SND_DEVICE_NONE &&
2758 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2759 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2760 __func__,
2761 use_case_table[uc_id],
2762 adev->last_logged_snd_device[uc_id][0],
2763 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2764 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2765 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2766 -1,
2767 out_snd_device,
2768 platform_get_snd_device_name(out_snd_device),
2769 platform_get_snd_device_acdb_id(out_snd_device));
2770 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2771 }
2772 if (in_snd_device != SND_DEVICE_NONE &&
2773 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2774 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2775 __func__,
2776 use_case_table[uc_id],
2777 adev->last_logged_snd_device[uc_id][1],
2778 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2779 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2780 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2781 -1,
2782 in_snd_device,
2783 platform_get_snd_device_name(in_snd_device),
2784 platform_get_snd_device_acdb_id(in_snd_device));
2785 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2786 }
2787
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002788
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789 /*
2790 * Limitation: While in call, to do a device switch we need to disable
2791 * and enable both RX and TX devices though one of them is same as current
2792 * device.
2793 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002794 if ((usecase->type == VOICE_CALL) &&
2795 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2796 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002797 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002798 }
2799
2800 if (((usecase->type == VOICE_CALL) ||
2801 (usecase->type == VOIP_CALL)) &&
2802 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2803 /* Disable sidetone only if voice/voip call already exists */
2804 if (voice_is_call_state_active(adev) ||
2805 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002806 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002807
2808 /* Disable aanc only if voice call exists */
2809 if (voice_is_call_state_active(adev))
2810 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002811 }
2812
Aalique Grahame22e49102018-12-18 14:23:57 -08002813 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2814 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002815 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302816 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002817 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2818 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2819 else
2820 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302821 }
2822
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002823 /* Disable current sound devices */
2824 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002825 disable_audio_route(adev, usecase);
2826 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 }
2828
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002829 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002830 disable_audio_route(adev, usecase);
2831 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832 }
2833
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002834 /* Applicable only on the targets that has external modem.
2835 * New device information should be sent to modem before enabling
2836 * the devices to reduce in-call device switch time.
2837 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002838 if ((usecase->type == VOICE_CALL) &&
2839 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2840 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002841 status = platform_switch_voice_call_enable_device_config(adev->platform,
2842 out_snd_device,
2843 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002844 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002845
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002846 /* Enable new sound devices */
2847 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002848 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302849 if (platform_check_codec_asrc_support(adev->platform))
2850 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002851 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852 }
2853
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002854 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302855 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002856 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002857 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002858
Avinash Vaish71a8b972014-07-24 15:36:33 +05302859 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002860 status = platform_switch_voice_call_device_post(adev->platform,
2861 out_snd_device,
2862 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302863 enable_audio_route_for_voice_usecases(adev, usecase);
2864 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002865
sangwoo170731f2013-06-08 15:36:36 +09002866 usecase->in_snd_device = in_snd_device;
2867 usecase->out_snd_device = out_snd_device;
2868
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302869 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2870 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302871 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002872 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002873 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002874 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2875 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2876 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2877 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2878 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2879 /*
2880 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2881 * configured device sample rate, if not update the COPP rate to be equal to the
2882 * device sample rate, else open COPP at stream sample rate
2883 */
2884 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2885 usecase->stream.out->sample_rate,
2886 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302887 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302888 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2889 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302890 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002891 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2892 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2893 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2894 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002895 }
2896 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002897
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002898 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002899
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002900 /* If input stream is already running then effect needs to be
2901 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002902 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002903 check_and_enable_effect(adev);
2904
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002905 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002906 /* Enable aanc only if voice call exists */
2907 if (voice_is_call_state_active(adev))
2908 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2909
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002910 /* Enable sidetone only if other voice/voip call already exists */
2911 if (voice_is_call_state_active(adev) ||
2912 voice_extn_compress_voip_is_started(adev))
2913 voice_set_sidetone(adev, out_snd_device, true);
2914 }
2915
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002916 /* Applicable only on the targets that has external modem.
2917 * Enable device command should be sent to modem only after
2918 * enabling voice call mixer controls
2919 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002920 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002921 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2922 out_snd_device,
2923 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302924
2925 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002926 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302927 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002928 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302929 if (is_bt_soc_on(adev) == false){
2930 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002931 if (in->pcm != NULL)
2932 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302933 }
2934 }
2935 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2936 && usecase->stream.out->started) {
2937 if (is_bt_soc_on(adev) == false) {
2938 ALOGD("BT SCO/A2DP disconnected while in connection");
2939 out_standby_l(&usecase->stream.out->stream.common);
2940 }
2941 }
2942 } else if ((usecase->stream.out != NULL) &&
2943 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302944 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2945 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08002946 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302947 usecase->stream.out->started) {
2948 if (is_bt_soc_on(adev) == false) {
2949 ALOGD("BT SCO/A2dp disconnected while in connection");
2950 out_standby_l(&usecase->stream.out->stream.common);
2951 }
2952 }
2953 }
2954
Yung Ti Su70cb8242018-06-22 17:38:47 +08002955 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002956 struct stream_out *voip_out = voip_usecase->stream.out;
2957 audio_extn_utils_send_app_type_gain(adev,
2958 voip_out->app_type_cfg.app_type,
2959 &voip_out->app_type_cfg.gain[0]);
2960 }
2961
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302962 ALOGD("%s: done",__func__);
2963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964 return status;
2965}
2966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967static int stop_input_stream(struct stream_in *in)
2968{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302969 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302971
2972 if (in == NULL) {
2973 ALOGE("%s: stream_in ptr is NULL", __func__);
2974 return -EINVAL;
2975 }
2976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002978 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979
Eric Laurent994a6932013-07-17 11:51:42 -07002980 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002981 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982 uc_info = get_usecase_from_list(adev, in->usecase);
2983 if (uc_info == NULL) {
2984 ALOGE("%s: Could not find the usecase (%d) in the list",
2985 __func__, in->usecase);
2986 return -EINVAL;
2987 }
2988
Carter Hsu2e429db2019-05-14 18:50:52 +08002989 priority_in = get_priority_input(adev);
2990
Derek Chenea197282019-01-07 17:35:01 -08002991 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2992 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002993
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002994 /* Close in-call recording streams */
2995 voice_check_and_stop_incall_rec_usecase(adev, in);
2996
Eric Laurent150dbfe2013-02-27 14:31:02 -08002997 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002998 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002999
3000 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003001 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003003 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303004 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3005
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003006 list_remove(&uc_info->list);
3007 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008
Carter Hsu2e429db2019-05-14 18:50:52 +08003009 if (priority_in == in) {
3010 priority_in = get_priority_input(adev);
3011 if (priority_in)
3012 select_devices(adev, priority_in->usecase);
3013 }
3014
Vatsal Buchac09ae062018-11-14 13:25:08 +05303015 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003016 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 return ret;
3018}
3019
3020int start_input_stream(struct stream_in *in)
3021{
3022 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003023 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303025
3026 if (in == NULL) {
3027 ALOGE("%s: stream_in ptr is NULL", __func__);
3028 return -EINVAL;
3029 }
3030
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003032 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003033 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034
Mingming Yin2664a5b2015-09-03 10:53:11 -07003035 if (get_usecase_from_list(adev, usecase) == NULL)
3036 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303037 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3038 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003039
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303040 if (CARD_STATUS_OFFLINE == in->card_status||
3041 CARD_STATUS_OFFLINE == adev->card_status) {
3042 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303043 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303044 goto error_config;
3045 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303046
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003047 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303048 if (!adev->bt_sco_on) {
3049 ALOGE("%s: SCO profile is not ready, return error", __func__);
3050 ret = -EIO;
3051 goto error_config;
3052 }
3053 }
3054
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003055 /* Check if source matches incall recording usecase criteria */
3056 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3057 if (ret)
3058 goto error_config;
3059 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003060 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3061
3062 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3063 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3064 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003065 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003066 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003067
Eric Laurentb23d5282013-05-14 15:27:20 -07003068 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 if (in->pcm_device_id < 0) {
3070 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3071 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003072 ret = -EINVAL;
3073 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003077
3078 if (!uc_info) {
3079 ret = -ENOMEM;
3080 goto error_config;
3081 }
3082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083 uc_info->id = in->usecase;
3084 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003085 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003086 list_init(&uc_info->device_list);
3087 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003088 uc_info->in_snd_device = SND_DEVICE_NONE;
3089 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003091 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003092 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303093 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3094 adev->perf_lock_opts,
3095 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003096 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097
Derek Chenea197282019-01-07 17:35:01 -08003098 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3099 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003100
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303101 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3102
Haynes Mathew George16081042017-05-31 17:16:49 -07003103 if (audio_extn_cin_attached_usecase(in->usecase)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303104 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303105 if (ret)
3106 goto error_open;
3107 else
3108 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003109 }
3110
Haynes Mathew George16081042017-05-31 17:16:49 -07003111 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003112 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003113 ALOGE("%s: pcm stream not ready", __func__);
3114 goto error_open;
3115 }
3116 ret = pcm_start(in->pcm);
3117 if (ret < 0) {
3118 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3119 goto error_open;
3120 }
3121 } else {
3122 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3123 unsigned int pcm_open_retry_count = 0;
3124
Zhou Song62ea0282020-03-22 19:53:01 +08003125 if ((in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) ||
3126 (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003127 flags |= PCM_MMAP | PCM_NOIRQ;
3128 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3129 } else if (in->realtime) {
3130 flags |= PCM_MMAP | PCM_NOIRQ;
3131 }
3132
Garmond Leunge2433c32017-09-28 21:51:22 -07003133 if (audio_extn_ffv_get_stream() == in) {
3134 ALOGD("%s: ffv stream, update pcm config", __func__);
3135 audio_extn_ffv_update_pcm_config(&config);
3136 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003137 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3138 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3139
3140 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003141 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003142 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003143 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003144 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303145 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303146 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3147 adev->card_status = CARD_STATUS_OFFLINE;
3148 in->card_status = CARD_STATUS_OFFLINE;
3149 ret = -EIO;
3150 goto error_open;
3151 }
3152
Haynes Mathew George16081042017-05-31 17:16:49 -07003153 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3154 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3155 if (in->pcm != NULL) {
3156 pcm_close(in->pcm);
3157 in->pcm = NULL;
3158 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003159 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003160 ret = -EIO;
3161 goto error_open;
3162 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003163 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003164 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3165 continue;
3166 }
3167 break;
3168 }
3169
3170 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003171 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003172 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003173 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003174 if (ret < 0) {
3175 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3176 pcm_close(in->pcm);
3177 in->pcm = NULL;
3178 goto error_open;
3179 }
3180 register_in_stream(in);
3181 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003182 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003183 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003184 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003185 if (ret < 0) {
3186 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003187 pcm_close(in->pcm);
3188 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003189 goto error_open;
3190 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003191 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003192 }
3193
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003194 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003195 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3196 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003197
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003198 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303199 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3200
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303201done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003202 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303203 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003204 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303205 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003206 return ret;
3207
3208error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003209 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303210 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003212
Eric Laurentc8400632013-02-14 19:04:54 -08003213error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303214 /*
3215 * sleep 50ms to allow sufficient time for kernel
3216 * drivers to recover incases like SSR.
3217 */
3218 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003219 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303220 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003221 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222}
3223
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003224void lock_input_stream(struct stream_in *in)
3225{
3226 pthread_mutex_lock(&in->pre_lock);
3227 pthread_mutex_lock(&in->lock);
3228 pthread_mutex_unlock(&in->pre_lock);
3229}
3230
3231void lock_output_stream(struct stream_out *out)
3232{
3233 pthread_mutex_lock(&out->pre_lock);
3234 pthread_mutex_lock(&out->lock);
3235 pthread_mutex_unlock(&out->pre_lock);
3236}
3237
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003238/* must be called with out->lock locked */
3239static int send_offload_cmd_l(struct stream_out* out, int command)
3240{
3241 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3242
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003243 if (!cmd) {
3244 ALOGE("failed to allocate mem for command 0x%x", command);
3245 return -ENOMEM;
3246 }
3247
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003248 ALOGVV("%s %d", __func__, command);
3249
3250 cmd->cmd = command;
3251 list_add_tail(&out->offload_cmd_list, &cmd->node);
3252 pthread_cond_signal(&out->offload_cond);
3253 return 0;
3254}
3255
3256/* must be called iwth out->lock locked */
3257static void stop_compressed_output_l(struct stream_out *out)
3258{
3259 out->offload_state = OFFLOAD_STATE_IDLE;
3260 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003261 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003262 if (out->compr != NULL) {
3263 compress_stop(out->compr);
3264 while (out->offload_thread_blocked) {
3265 pthread_cond_wait(&out->cond, &out->lock);
3266 }
3267 }
3268}
3269
Varun Balaraje49253e2017-07-06 19:48:56 +05303270bool is_interactive_usecase(audio_usecase_t uc_id)
3271{
3272 unsigned int i;
3273 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3274 if (uc_id == interactive_usecases[i])
3275 return true;
3276 }
3277 return false;
3278}
3279
3280static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3281{
3282 audio_usecase_t ret_uc = USECASE_INVALID;
3283 unsigned int intract_uc_index;
3284 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3285
3286 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3287 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3288 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3289 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3290 ret_uc = interactive_usecases[intract_uc_index];
3291 break;
3292 }
3293 }
3294
3295 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3296 return ret_uc;
3297}
3298
3299static void free_interactive_usecase(struct audio_device *adev,
3300 audio_usecase_t uc_id)
3301{
3302 unsigned int interact_uc_index;
3303 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3304
3305 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3306 if (interactive_usecases[interact_uc_index] == uc_id) {
3307 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3308 break;
3309 }
3310 }
3311 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3312}
3313
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003314bool is_offload_usecase(audio_usecase_t uc_id)
3315{
3316 unsigned int i;
3317 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3318 if (uc_id == offload_usecases[i])
3319 return true;
3320 }
3321 return false;
3322}
3323
Dhananjay Kumarac341582017-02-23 23:42:25 +05303324static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003325{
vivek mehta446c3962015-09-14 10:57:35 -07003326 audio_usecase_t ret_uc = USECASE_INVALID;
3327 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003328 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003329 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303330 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003331 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3332 else
3333 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003334
vivek mehta446c3962015-09-14 10:57:35 -07003335 pthread_mutex_lock(&adev->lock);
3336 if (get_usecase_from_list(adev, ret_uc) != NULL)
3337 ret_uc = USECASE_INVALID;
3338 pthread_mutex_unlock(&adev->lock);
3339
3340 return ret_uc;
3341 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003342
3343 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003344 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3345 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3346 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3347 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003348 break;
3349 }
3350 }
vivek mehta446c3962015-09-14 10:57:35 -07003351
3352 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3353 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003354}
3355
3356static void free_offload_usecase(struct audio_device *adev,
3357 audio_usecase_t uc_id)
3358{
vivek mehta446c3962015-09-14 10:57:35 -07003359 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003360 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003361
3362 if (!adev->multi_offload_enable)
3363 return;
3364
3365 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3366 if (offload_usecases[offload_uc_index] == uc_id) {
3367 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003368 break;
3369 }
3370 }
3371 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3372}
3373
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003374static void *offload_thread_loop(void *context)
3375{
3376 struct stream_out *out = (struct stream_out *) context;
3377 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003378 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003379
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003380 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003381 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003382 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3383
3384 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003385 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003386 out->offload_state = OFFLOAD_STATE_IDLE;
3387 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003388 for (;;) {
3389 struct offload_cmd *cmd = NULL;
3390 stream_callback_event_t event;
3391 bool send_callback = false;
3392
3393 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3394 __func__, list_empty(&out->offload_cmd_list),
3395 out->offload_state);
3396 if (list_empty(&out->offload_cmd_list)) {
3397 ALOGV("%s SLEEPING", __func__);
3398 pthread_cond_wait(&out->offload_cond, &out->lock);
3399 ALOGV("%s RUNNING", __func__);
3400 continue;
3401 }
3402
3403 item = list_head(&out->offload_cmd_list);
3404 cmd = node_to_item(item, struct offload_cmd, node);
3405 list_remove(item);
3406
3407 ALOGVV("%s STATE %d CMD %d out->compr %p",
3408 __func__, out->offload_state, cmd->cmd, out->compr);
3409
3410 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3411 free(cmd);
3412 break;
3413 }
3414
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003415 // allow OFFLOAD_CMD_ERROR reporting during standby
3416 // this is needed to handle failures during compress_open
3417 // Note however that on a pause timeout, the stream is closed
3418 // and no offload usecase will be active. Therefore this
3419 // special case is needed for compress_open failures alone
3420 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3421 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003422 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003423 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003424 pthread_cond_signal(&out->cond);
3425 continue;
3426 }
3427 out->offload_thread_blocked = true;
3428 pthread_mutex_unlock(&out->lock);
3429 send_callback = false;
3430 switch(cmd->cmd) {
3431 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003432 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003433 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003434 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435 send_callback = true;
3436 event = STREAM_CBK_EVENT_WRITE_READY;
3437 break;
3438 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003439 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303440 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003441 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303442 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003443 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303444 if (ret < 0)
3445 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303446 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303447 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003448 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003449 else
3450 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003451 if (-ENETRESET != ret && !(-EINTR == ret &&
3452 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303453 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303454 pthread_mutex_lock(&out->lock);
3455 out->send_new_metadata = 1;
3456 out->send_next_track_params = true;
3457 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303458 event = STREAM_CBK_EVENT_DRAIN_READY;
3459 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3460 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303461 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003462 break;
3463 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003464 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003465 ret = compress_drain(out->compr);
3466 ALOGD("copl(%p):out of compress_drain", out);
3467 // EINTR check avoids drain interruption due to SSR
3468 if (-ENETRESET != ret && !(-EINTR == ret &&
3469 CARD_STATUS_OFFLINE == out->card_status)) {
3470 send_callback = true;
3471 event = STREAM_CBK_EVENT_DRAIN_READY;
3472 } else
3473 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003474 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303475 case OFFLOAD_CMD_ERROR:
3476 ALOGD("copl(%p): sending error callback to AF", out);
3477 send_callback = true;
3478 event = STREAM_CBK_EVENT_ERROR;
3479 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003480 default:
3481 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3482 break;
3483 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003484 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003485 out->offload_thread_blocked = false;
3486 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003487 if (send_callback && out->client_callback) {
3488 ALOGVV("%s: sending client_callback event %d", __func__, event);
3489 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003490 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003491 free(cmd);
3492 }
3493
3494 pthread_cond_signal(&out->cond);
3495 while (!list_empty(&out->offload_cmd_list)) {
3496 item = list_head(&out->offload_cmd_list);
3497 list_remove(item);
3498 free(node_to_item(item, struct offload_cmd, node));
3499 }
3500 pthread_mutex_unlock(&out->lock);
3501
3502 return NULL;
3503}
3504
3505static int create_offload_callback_thread(struct stream_out *out)
3506{
3507 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3508 list_init(&out->offload_cmd_list);
3509 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3510 offload_thread_loop, out);
3511 return 0;
3512}
3513
3514static int destroy_offload_callback_thread(struct stream_out *out)
3515{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003516 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003517 stop_compressed_output_l(out);
3518 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3519
3520 pthread_mutex_unlock(&out->lock);
3521 pthread_join(out->offload_thread, (void **) NULL);
3522 pthread_cond_destroy(&out->offload_cond);
3523
3524 return 0;
3525}
3526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527static int stop_output_stream(struct stream_out *out)
3528{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303529 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 struct audio_usecase *uc_info;
3531 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003532 bool has_voip_usecase =
3533 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534
Eric Laurent994a6932013-07-17 11:51:42 -07003535 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003536 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003537 uc_info = get_usecase_from_list(adev, out->usecase);
3538 if (uc_info == NULL) {
3539 ALOGE("%s: Could not find the usecase (%d) in the list",
3540 __func__, out->usecase);
3541 return -EINVAL;
3542 }
3543
Derek Chenea197282019-01-07 17:35:01 -08003544 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3545 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003546
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003547 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303548 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003549 if (adev->visualizer_stop_output != NULL)
3550 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003551
3552 audio_extn_dts_remove_state_notifier_node(out->usecase);
3553
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003554 if (adev->offload_effects_stop_output != NULL)
3555 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003556 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3557 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3558 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003559 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003560
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003561 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3562 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003563 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003564 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003565
Eric Laurent150dbfe2013-02-27 14:31:02 -08003566 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003567 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003568
3569 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003570 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571
Aalique Grahame22e49102018-12-18 14:23:57 -08003572 audio_extn_extspk_update(adev->extspk);
3573
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003574 if (is_offload_usecase(out->usecase)) {
3575 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3576 adev->dsp_bit_width_enforce_mode,
3577 false);
3578 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003579 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003580 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3581 false);
3582
3583 if (ret != 0)
3584 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3585 /* default service interval was successfully updated,
3586 reopen USB backend with new service interval */
3587 ret = 0;
3588 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003589
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003590 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303591 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003592 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303593 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003594 ALOGV("Disable passthrough , reset mixer to pcm");
3595 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003596#ifdef AUDIO_GKI_ENABLED
3597 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3598 out->compr_config.codec->reserved[0] = 0;
3599#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003600 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003601#endif
Mingming Yin21854652016-04-13 11:54:02 -07003602 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003603 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3604 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003605
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303606 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003607 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303608 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303609
Manish Dewangan21a850a2017-08-14 12:03:55 +05303610 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003611 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3612 if (ret < 0)
3613 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3614 }
3615
juyuchen2d415992018-11-16 14:15:16 +08003616 /* 1) media + voip output routing to handset must route media back to
3617 speaker when voip stops.
3618 2) trigger voip input to reroute when voip output changes to
3619 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003620 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003621 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003622 struct listnode *node;
3623 struct audio_usecase *usecase;
3624 list_for_each(node, &adev->usecase_list) {
3625 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003626 if ((usecase->type == PCM_CAPTURE &&
3627 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3628 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003629 continue;
3630
3631 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3632 __func__, usecase->id, use_case_table[usecase->id],
3633 out->usecase, use_case_table[out->usecase]);
3634 select_devices(adev, usecase->id);
3635 }
3636 }
3637
Garmond Leung5fd0b552018-04-17 11:56:12 -07003638 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003639 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640 return ret;
3641}
3642
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003643struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3644 unsigned int flags, unsigned int pcm_open_retry_count,
3645 struct pcm_config *config)
3646{
3647 struct pcm* pcm = NULL;
3648
3649 while (1) {
3650 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3651 if (pcm == NULL || !pcm_is_ready(pcm)) {
3652 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3653 if (pcm != NULL) {
3654 pcm_close(pcm);
3655 pcm = NULL;
3656 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003657 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003658 return NULL;
3659
Weiyin Jiang72197252019-10-09 11:49:32 +08003660 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003661 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3662 continue;
3663 }
3664 break;
3665 }
3666
3667 if (pcm_is_ready(pcm)) {
3668 int ret = pcm_prepare(pcm);
3669 if (ret < 0) {
3670 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3671 pcm_close(pcm);
3672 pcm = NULL;
3673 }
3674 }
3675
3676 return pcm;
3677}
3678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679int start_output_stream(struct stream_out *out)
3680{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 struct audio_usecase *uc_info;
3683 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003684 char mixer_ctl_name[128];
3685 struct mixer_ctl *ctl = NULL;
3686 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303687 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003688 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689
Haynes Mathew George380745d2017-10-04 15:27:45 -07003690 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003691 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3692 ret = -EINVAL;
3693 goto error_config;
3694 }
3695
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003696 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303697 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003698 get_device_types(&out->device_list), is_haptic_usecase);
3699
3700 bool is_speaker_active = compare_device_type(&out->device_list,
3701 AUDIO_DEVICE_OUT_SPEAKER);
3702 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3703 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303704
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303705 if (CARD_STATUS_OFFLINE == out->card_status ||
3706 CARD_STATUS_OFFLINE == adev->card_status) {
3707 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303708 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003709 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303710 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303711
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003712 //Update incall music usecase to reflect correct voice session
3713 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3714 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3715 if (ret != 0) {
3716 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3717 __func__, ret);
3718 goto error_config;
3719 }
3720 }
3721
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003722 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003723 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003724 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303725 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303726 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303727 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3728 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3729 ret = -EAGAIN;
3730 goto error_config;
3731 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303732 }
3733 }
3734 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003735 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303736 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003737 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303738 //combo usecase just by pass a2dp
3739 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003740 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303741 } else {
3742 ALOGE("%s: SCO profile is not ready, return error", __func__);
3743 ret = -EAGAIN;
3744 goto error_config;
3745 }
3746 }
3747 }
3748
Eric Laurentb23d5282013-05-14 15:27:20 -07003749 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 if (out->pcm_device_id < 0) {
3751 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3752 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003753 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003754 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755 }
3756
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003757 if (is_haptic_usecase) {
3758 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3759 if (adev->haptic_pcm_device_id < 0) {
3760 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3761 __func__, adev->haptic_pcm_device_id, out->usecase);
3762 ret = -EINVAL;
3763 goto error_config;
3764 }
3765 }
3766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003768
3769 if (!uc_info) {
3770 ret = -ENOMEM;
3771 goto error_config;
3772 }
3773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 uc_info->id = out->usecase;
3775 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003776 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003777 list_init(&uc_info->device_list);
3778 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003779 uc_info->in_snd_device = SND_DEVICE_NONE;
3780 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003781
3782 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003783 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003784 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3785 /* USB backend is not reopened immediately.
3786 This is eventually done as part of select_devices */
3787 }
3788
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003789 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790
Wei Wangf7ca6c92017-11-21 14:51:20 -08003791 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303792 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3793 adev->perf_lock_opts,
3794 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303795
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003796 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303797 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303798 if (audio_extn_passthru_is_enabled() &&
3799 audio_extn_passthru_is_passthrough_stream(out)) {
3800 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303801 }
3802 }
3803
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003804 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003805 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303806 if (!a2dp_combo) {
3807 check_a2dp_restore_l(adev, out, false);
3808 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003809 struct listnode dev;
3810 list_init(&dev);
3811 assign_devices(&dev, &out->device_list);
3812 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3813 reassign_device_list(&out->device_list,
3814 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003815 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003816 reassign_device_list(&out->device_list,
3817 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303818 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003819 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303820 }
3821 } else {
3822 select_devices(adev, out->usecase);
3823 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003824
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003825 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3826 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003827 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003828 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003829
Derek Chenea197282019-01-07 17:35:01 -08003830 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3831 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003832
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003833 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3834 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003835
3836 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003837 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003838 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3839 ALOGE("%s: pcm stream not ready", __func__);
3840 goto error_open;
3841 }
3842 ret = pcm_start(out->pcm);
3843 if (ret < 0) {
3844 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3845 goto error_open;
3846 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003847 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003848 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003849 unsigned int flags = PCM_OUT;
3850 unsigned int pcm_open_retry_count = 0;
3851 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3852 flags |= PCM_MMAP | PCM_NOIRQ;
3853 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003854 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003855 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003856 } else
3857 flags |= PCM_MONOTONIC;
3858
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003859 if ((adev->vr_audio_mode_enabled) &&
3860 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3861 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3862 "PCM_Dev %d Topology", out->pcm_device_id);
3863 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3864 if (!ctl) {
3865 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3866 __func__, mixer_ctl_name);
3867 } else {
3868 //if success use ULLPP
3869 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3870 __func__, mixer_ctl_name, out->pcm_device_id);
3871 //There is a still a possibility that some sessions
3872 // that request for FAST|RAW when 3D audio is active
3873 //can go through ULLPP. Ideally we expects apps to
3874 //listen to audio focus and stop concurrent playback
3875 //Also, we will look for mode flag (voice_in_communication)
3876 //before enabling the realtime flag.
3877 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3878 }
3879 }
3880
Surendar Karka91fa3682018-07-02 18:12:12 +05303881 if (out->realtime)
3882 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3883 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3884
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003885 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3886 flags, pcm_open_retry_count,
3887 &(out->config));
3888 if (out->pcm == NULL) {
3889 ret = -EIO;
3890 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003891 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003892
3893 if (is_haptic_usecase) {
3894 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3895 adev->haptic_pcm_device_id,
3896 flags, pcm_open_retry_count,
3897 &(adev->haptics_config));
3898 // failure to open haptics pcm shouldnt stop audio,
3899 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003900
3901 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3902 ALOGD("%s: enable haptic audio synchronization", __func__);
3903 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3904 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003905 }
3906
Surendar Karka91fa3682018-07-02 18:12:12 +05303907 if (!out->realtime)
3908 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303909 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003910
Zhou Song2b8f28f2017-09-11 10:51:38 +08003911 // apply volume for voip playback after path is set up
3912 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3913 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303914 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3915 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303916 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3917 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003918 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3919 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303920 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003921 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003922 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303923 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003924 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3925 adev->dsp_bit_width_enforce_mode,
3926 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003928 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003929 out->compr = compress_open(adev->snd_card,
3930 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003931 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003932 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303933 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303934 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3935 adev->card_status = CARD_STATUS_OFFLINE;
3936 out->card_status = CARD_STATUS_OFFLINE;
3937 ret = -EIO;
3938 goto error_open;
3939 }
3940
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003941 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003942 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003943 compress_close(out->compr);
3944 out->compr = NULL;
3945 ret = -EIO;
3946 goto error_open;
3947 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303948 /* compress_open sends params of the track, so reset the flag here */
3949 out->is_compr_metadata_avail = false;
3950
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003951 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003952 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003953
Fred Oh3f43e742015-03-04 18:42:34 -08003954 /* Since small bufs uses blocking writes, a write will be blocked
3955 for the default max poll time (20s) in the event of an SSR.
3956 Reduce the poll time to observe and deal with SSR faster.
3957 */
Ashish Jain5106d362016-05-11 19:23:33 +05303958 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003959 compress_set_max_poll_wait(out->compr, 1000);
3960 }
3961
Manish Dewangan69426c82017-01-30 17:35:36 +05303962 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303963 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303964
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003965 audio_extn_dts_create_state_notifier_node(out->usecase);
3966 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3967 popcount(out->channel_mask),
3968 out->playback_started);
3969
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003970#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303971 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003972 audio_extn_dolby_send_ddp_endp_params(adev);
3973#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303974 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3975 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003976 if (adev->visualizer_start_output != NULL)
3977 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3978 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303979 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003980 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003981 }
Derek Chenf13dd492018-11-13 14:53:51 -08003982
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003983 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08003984 /* Update cached volume from media to offload/direct stream */
3985 struct listnode *node = NULL;
3986 list_for_each(node, &adev->active_outputs_list) {
3987 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3988 streams_output_ctxt_t,
3989 list);
3990 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3991 out->volume_l = out_ctxt->output->volume_l;
3992 out->volume_r = out_ctxt->output->volume_r;
3993 }
3994 }
3995 out_set_compr_volume(&out->stream,
3996 out->volume_l, out->volume_r);
3997 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003998 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003999
4000 if (ret == 0) {
4001 register_out_stream(out);
4002 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004003 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4004 ALOGE("%s: pcm stream not ready", __func__);
4005 goto error_open;
4006 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004007 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004008 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004009 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004010 if (ret < 0)
4011 goto error_open;
4012 }
4013 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004014 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304015 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004016 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004017
vivek mehtad15d2bf2019-05-17 13:35:10 -07004018 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4019 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4020 audio_low_latency_hint_start();
4021 }
4022
Manish Dewangan21a850a2017-08-14 12:03:55 +05304023 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004024 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004025 if (ret < 0)
4026 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4027 }
4028
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004029 // consider a scenario where on pause lower layers are tear down.
4030 // so on resume, swap mixer control need to be sent only when
4031 // backend is active, hence rather than sending from enable device
4032 // sending it from start of streamtream
4033
4034 platform_set_swap_channels(adev, true);
4035
Haynes Mathew George380745d2017-10-04 15:27:45 -07004036 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304037 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004038 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004039error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004040 if (adev->haptic_pcm) {
4041 pcm_close(adev->haptic_pcm);
4042 adev->haptic_pcm = NULL;
4043 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004044 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304045 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004047error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304048 /*
4049 * sleep 50ms to allow sufficient time for kernel
4050 * drivers to recover incases like SSR.
4051 */
4052 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004053error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004054 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304055 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004056 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004057}
4058
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004059static int check_input_parameters(uint32_t sample_rate,
4060 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004061 int channel_count,
4062 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004063{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004064 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304066 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4067 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4068 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004069 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004070 !audio_extn_compr_cap_format_supported(format) &&
4071 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004072 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004073
Aalique Grahame22e49102018-12-18 14:23:57 -08004074 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4075 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4076 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4077 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4078 return -EINVAL;
4079 }
4080
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004081 switch (channel_count) {
4082 case 1:
4083 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304084 case 3:
4085 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004086 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004087 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304088 case 10:
4089 case 12:
4090 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004091 break;
4092 default:
4093 ret = -EINVAL;
4094 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004095
4096 switch (sample_rate) {
4097 case 8000:
4098 case 11025:
4099 case 12000:
4100 case 16000:
4101 case 22050:
4102 case 24000:
4103 case 32000:
4104 case 44100:
4105 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004106 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304107 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004108 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304109 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004110 break;
4111 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004112 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113 }
4114
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004115 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004116}
4117
Naresh Tanniru04f71882018-06-26 17:46:22 +05304118
4119/** Add a value in a list if not already present.
4120 * @return true if value was successfully inserted or already present,
4121 * false if the list is full and does not contain the value.
4122 */
4123static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4124 for (size_t i = 0; i < list_length; i++) {
4125 if (list[i] == value) return true; // value is already present
4126 if (list[i] == 0) { // no values in this slot
4127 list[i] = value;
4128 return true; // value inserted
4129 }
4130 }
4131 return false; // could not insert value
4132}
4133
4134/** Add channel_mask in supported_channel_masks if not already present.
4135 * @return true if channel_mask was successfully inserted or already present,
4136 * false if supported_channel_masks is full and does not contain channel_mask.
4137 */
4138static void register_channel_mask(audio_channel_mask_t channel_mask,
4139 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4140 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4141 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4142}
4143
4144/** Add format in supported_formats if not already present.
4145 * @return true if format was successfully inserted or already present,
4146 * false if supported_formats is full and does not contain format.
4147 */
4148static void register_format(audio_format_t format,
4149 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4150 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4151 "%s: stream can not declare supporting its format %x", __func__, format);
4152}
4153/** Add sample_rate in supported_sample_rates if not already present.
4154 * @return true if sample_rate was successfully inserted or already present,
4155 * false if supported_sample_rates is full and does not contain sample_rate.
4156 */
4157static void register_sample_rate(uint32_t sample_rate,
4158 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4159 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4160 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4161}
4162
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004163static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4164{
4165 uint32_t high = num1, low = num2, temp = 0;
4166
4167 if (!num1 || !num2)
4168 return 0;
4169
4170 if (num1 < num2) {
4171 high = num2;
4172 low = num1;
4173 }
4174
4175 while (low != 0) {
4176 temp = low;
4177 low = high % low;
4178 high = temp;
4179 }
4180 return (num1 * num2)/high;
4181}
4182
4183static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4184{
4185 uint32_t remainder = 0;
4186
4187 if (!multiplier)
4188 return num;
4189
4190 remainder = num % multiplier;
4191 if (remainder)
4192 num += (multiplier - remainder);
4193
4194 return num;
4195}
4196
Aalique Grahame22e49102018-12-18 14:23:57 -08004197static size_t get_stream_buffer_size(size_t duration_ms,
4198 uint32_t sample_rate,
4199 audio_format_t format,
4200 int channel_count,
4201 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202{
4203 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004204 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004205
Aalique Grahame22e49102018-12-18 14:23:57 -08004206 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004207 if (is_low_latency)
4208 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304209
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004210 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004211 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212
Ralf Herzbd08d632018-09-28 15:50:49 +02004213 /* make sure the size is multiple of 32 bytes and additionally multiple of
4214 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004215 * At 48 kHz mono 16-bit PCM:
4216 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4217 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004218 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004219 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004220 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004221
4222 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223}
4224
Aalique Grahame22e49102018-12-18 14:23:57 -08004225static size_t get_input_buffer_size(uint32_t sample_rate,
4226 audio_format_t format,
4227 int channel_count,
4228 bool is_low_latency)
4229{
4230 /* Don't know if USB HIFI in this context so use true to be conservative */
4231 if (check_input_parameters(sample_rate, format, channel_count,
4232 true /*is_usb_hifi */) != 0)
4233 return 0;
4234
4235 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4236 sample_rate,
4237 format,
4238 channel_count,
4239 is_low_latency);
4240}
4241
Derek Chenf6318be2017-06-12 17:16:24 -04004242size_t get_output_period_size(uint32_t sample_rate,
4243 audio_format_t format,
4244 int channel_count,
4245 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304246{
4247 size_t size = 0;
4248 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4249
4250 if ((duration == 0) || (sample_rate == 0) ||
4251 (bytes_per_sample == 0) || (channel_count == 0)) {
4252 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4253 bytes_per_sample, channel_count);
4254 return -EINVAL;
4255 }
4256
4257 size = (sample_rate *
4258 duration *
4259 bytes_per_sample *
4260 channel_count) / 1000;
4261 /*
4262 * To have same PCM samples for all channels, the buffer size requires to
4263 * be multiple of (number of channels * bytes per sample)
4264 * For writes to succeed, the buffer must be written at address which is multiple of 32
4265 */
4266 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4267
4268 return (size/(channel_count * bytes_per_sample));
4269}
4270
Zhou Song48453a02018-01-10 17:50:59 +08004271static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304272{
4273 uint64_t actual_frames_rendered = 0;
4274 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4275
4276 /* This adjustment accounts for buffering after app processor.
4277 * It is based on estimated DSP latency per use case, rather than exact.
4278 */
4279 int64_t platform_latency = platform_render_latency(out->usecase) *
4280 out->sample_rate / 1000000LL;
4281
Zhou Song48453a02018-01-10 17:50:59 +08004282 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304283 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4284 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4285 * hence only estimate.
4286 */
George Gao62ebc722019-07-29 16:29:44 -07004287 uint64_t signed_frames = 0;
4288 if (out->written >= kernel_buffer_size)
4289 signed_frames = out->written - kernel_buffer_size;
Ashish Jain5106d362016-05-11 19:23:33 +05304290
George Gao62ebc722019-07-29 16:29:44 -07004291 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask));
4292 if (signed_frames >= platform_latency)
4293 signed_frames = signed_frames - platform_latency;
Ashish Jain5106d362016-05-11 19:23:33 +05304294
Zhou Song48453a02018-01-10 17:50:59 +08004295 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304296 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004297 if (timestamp != NULL )
4298 *timestamp = out->writeAt;
4299 } else if (timestamp != NULL) {
4300 clock_gettime(CLOCK_MONOTONIC, timestamp);
4301 }
4302 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304303
4304 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
George Gao62ebc722019-07-29 16:29:44 -07004305 "bytes/sample %zu channel count %d", __func__, signed_frames,
Ashish Jain5106d362016-05-11 19:23:33 +05304306 (long long int)out->written, (int)kernel_buffer_size,
4307 audio_bytes_per_sample(out->compr_config.codec->format),
4308 popcount(out->channel_mask));
4309
4310 return actual_frames_rendered;
4311}
4312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4314{
4315 struct stream_out *out = (struct stream_out *)stream;
4316
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004317 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318}
4319
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004320static int out_set_sample_rate(struct audio_stream *stream __unused,
4321 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322{
4323 return -ENOSYS;
4324}
4325
4326static size_t out_get_buffer_size(const struct audio_stream *stream)
4327{
4328 struct stream_out *out = (struct stream_out *)stream;
4329
Varun Balaraje49253e2017-07-06 19:48:56 +05304330 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304331 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304332 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304333 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4334 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4335 else
4336 return out->compr_config.fragment_size;
4337 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004338 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304339 else if (is_offload_usecase(out->usecase) &&
4340 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304341 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004342
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004343 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004344 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004345}
4346
4347static uint32_t out_get_channels(const struct audio_stream *stream)
4348{
4349 struct stream_out *out = (struct stream_out *)stream;
4350
4351 return out->channel_mask;
4352}
4353
4354static audio_format_t out_get_format(const struct audio_stream *stream)
4355{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004356 struct stream_out *out = (struct stream_out *)stream;
4357
4358 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004359}
4360
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004361static int out_set_format(struct audio_stream *stream __unused,
4362 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004363{
4364 return -ENOSYS;
4365}
4366
4367static int out_standby(struct audio_stream *stream)
4368{
4369 struct stream_out *out = (struct stream_out *)stream;
4370 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004371 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004372
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304373 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4374 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004376 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004378 if (adev->adm_deregister_stream)
4379 adev->adm_deregister_stream(adev->adm_data, out->handle);
4380
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004381 if (is_offload_usecase(out->usecase))
4382 stop_compressed_output_l(out);
4383
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004384 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004385 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004386 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4387 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304388 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004389 pthread_mutex_unlock(&adev->lock);
4390 pthread_mutex_unlock(&out->lock);
4391 ALOGD("VOIP output entered standby");
4392 return 0;
4393 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004394 if (out->pcm) {
4395 pcm_close(out->pcm);
4396 out->pcm = NULL;
4397 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004398 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4399 do_stop = out->playback_started;
4400 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004401
4402 if (out->mmap_shared_memory_fd >= 0) {
4403 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4404 __func__, out->mmap_shared_memory_fd);
4405 close(out->mmap_shared_memory_fd);
4406 out->mmap_shared_memory_fd = -1;
4407 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004408 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004409 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004410 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304411 out->send_next_track_params = false;
4412 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004413 out->gapless_mdata.encoder_delay = 0;
4414 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004415 if (out->compr != NULL) {
4416 compress_close(out->compr);
4417 out->compr = NULL;
4418 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004419 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004420 if (do_stop) {
4421 stop_output_stream(out);
4422 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304423 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004424 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004425 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004426 }
4427 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304428 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004429 return 0;
4430}
4431
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304432static int out_on_error(struct audio_stream *stream)
4433{
4434 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004435 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304436
4437 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004438 // always send CMD_ERROR for offload streams, this
4439 // is needed e.g. when SSR happens within compress_open
4440 // since the stream is active, offload_callback_thread is also active.
4441 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4442 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004443 }
4444 pthread_mutex_unlock(&out->lock);
4445
4446 status = out_standby(&out->stream.common);
4447
4448 lock_output_stream(out);
4449 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004450 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304451 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304452
4453 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4454 ALOGD("Setting previous card status if offline");
4455 out->prev_card_status_offline = true;
4456 }
4457
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304458 pthread_mutex_unlock(&out->lock);
4459
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004460 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304461}
4462
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304463/*
4464 *standby implementation without locks, assumes that the callee already
4465 *has taken adev and out lock.
4466 */
4467int out_standby_l(struct audio_stream *stream)
4468{
4469 struct stream_out *out = (struct stream_out *)stream;
4470 struct audio_device *adev = out->dev;
4471
4472 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4473 stream, out->usecase, use_case_table[out->usecase]);
4474
4475 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004476 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304477 if (adev->adm_deregister_stream)
4478 adev->adm_deregister_stream(adev->adm_data, out->handle);
4479
4480 if (is_offload_usecase(out->usecase))
4481 stop_compressed_output_l(out);
4482
4483 out->standby = true;
4484 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4485 voice_extn_compress_voip_close_output_stream(stream);
4486 out->started = 0;
4487 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004488 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304489 return 0;
4490 } else if (!is_offload_usecase(out->usecase)) {
4491 if (out->pcm) {
4492 pcm_close(out->pcm);
4493 out->pcm = NULL;
4494 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004495 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4496 if (adev->haptic_pcm) {
4497 pcm_close(adev->haptic_pcm);
4498 adev->haptic_pcm = NULL;
4499 }
4500
4501 if (adev->haptic_buffer != NULL) {
4502 free(adev->haptic_buffer);
4503 adev->haptic_buffer = NULL;
4504 adev->haptic_buffer_size = 0;
4505 }
4506 adev->haptic_pcm_device_id = 0;
4507 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304508 } else {
4509 ALOGD("copl(%p):standby", out);
4510 out->send_next_track_params = false;
4511 out->is_compr_metadata_avail = false;
4512 out->gapless_mdata.encoder_delay = 0;
4513 out->gapless_mdata.encoder_padding = 0;
4514 if (out->compr != NULL) {
4515 compress_close(out->compr);
4516 out->compr = NULL;
4517 }
4518 }
4519 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004520 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304521 }
4522 ALOGD("%s: exit", __func__);
4523 return 0;
4524}
4525
Aalique Grahame22e49102018-12-18 14:23:57 -08004526static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527{
Aalique Grahame22e49102018-12-18 14:23:57 -08004528 struct stream_out *out = (struct stream_out *)stream;
4529
4530 // We try to get the lock for consistency,
4531 // but it isn't necessary for these variables.
4532 // If we're not in standby, we may be blocked on a write.
4533 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4534 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4535 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4536
4537 if (locked) {
4538 pthread_mutex_unlock(&out->lock);
4539 }
4540
4541 // dump error info
4542 (void)error_log_dump(
4543 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4544
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004545 return 0;
4546}
4547
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004548static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4549{
4550 int ret = 0;
4551 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004552
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004553 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004554 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004555 return -EINVAL;
4556 }
4557
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304558 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004559
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004560 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4561 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304562 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004563 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004564 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4565 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304566 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004567 }
4568
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004569 ALOGV("%s new encoder delay %u and padding %u", __func__,
4570 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4571
4572 return 0;
4573}
4574
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004575static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4576{
4577 return out == adev->primary_output || out == adev->voice_tx_output;
4578}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004579
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304580// note: this call is safe only if the stream_cb is
4581// removed first in close_output_stream (as is done now).
4582static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4583{
4584 if (!stream || !parms)
4585 return;
4586
4587 struct stream_out *out = (struct stream_out *)stream;
4588 struct audio_device *adev = out->dev;
4589
4590 card_status_t status;
4591 int card;
4592 if (parse_snd_card_status(parms, &card, &status) < 0)
4593 return;
4594
4595 pthread_mutex_lock(&adev->lock);
4596 bool valid_cb = (card == adev->snd_card);
4597 pthread_mutex_unlock(&adev->lock);
4598
4599 if (!valid_cb)
4600 return;
4601
4602 lock_output_stream(out);
4603 if (out->card_status != status)
4604 out->card_status = status;
4605 pthread_mutex_unlock(&out->lock);
4606
4607 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4608 use_case_table[out->usecase],
4609 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4610
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304611 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304612 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304613 if (voice_is_call_state_active(adev) &&
4614 out == adev->primary_output) {
4615 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4616 pthread_mutex_lock(&adev->lock);
4617 voice_stop_call(adev);
4618 adev->mode = AUDIO_MODE_NORMAL;
4619 pthread_mutex_unlock(&adev->lock);
4620 }
4621 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304622 return;
4623}
4624
Kevin Rocardfce19002017-08-07 19:21:36 -07004625static int get_alive_usb_card(struct str_parms* parms) {
4626 int card;
4627 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4628 !audio_extn_usb_alive(card)) {
4629 return card;
4630 }
4631 return -ENODEV;
4632}
4633
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004634int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004635 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004636{
4637 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004638 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004639 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004640 bool bypass_a2dp = false;
4641 bool reconfig = false;
4642 unsigned long service_interval = 0;
4643
4644 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004645 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4646
4647 list_init(&new_devices);
4648 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004649
4650 lock_output_stream(out);
4651 pthread_mutex_lock(&adev->lock);
4652
4653 /*
4654 * When HDMI cable is unplugged the music playback is paused and
4655 * the policy manager sends routing=0. But the audioflinger continues
4656 * to write data until standby time (3sec). As the HDMI core is
4657 * turned off, the write gets blocked.
4658 * Avoid this by routing audio to speaker until standby.
4659 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004660 if (is_single_device_type_equal(&out->device_list,
4661 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004662 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004663 !audio_extn_passthru_is_passthrough_stream(out) &&
4664 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004665 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004666 }
4667 /*
4668 * When A2DP is disconnected the
4669 * music playback is paused and the policy manager sends routing=0
4670 * But the audioflinger continues to write data until standby time
4671 * (3sec). As BT is turned off, the write gets blocked.
4672 * Avoid this by routing audio to speaker until standby.
4673 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004674 if (is_a2dp_out_device_type(&out->device_list) &&
4675 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004676 !audio_extn_a2dp_source_is_ready() &&
4677 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004678 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004679 }
4680 /*
4681 * When USB headset is disconnected the music platback paused
4682 * and the policy manager send routing=0. But if the USB is connected
4683 * back before the standby time, AFE is not closed and opened
4684 * when USB is connected back. So routing to speker will guarantee
4685 * AFE reconfiguration and AFE will be opend once USB is connected again
4686 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004687 if (is_usb_out_device_type(&out->device_list) &&
4688 list_empty(&new_devices) &&
4689 !audio_extn_usb_connected(NULL)) {
4690 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4691 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004692 /* To avoid a2dp to sco overlapping / BT device improper state
4693 * check with BT lib about a2dp streaming support before routing
4694 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004695 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004696 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004697 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4698 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004699 //combo usecase just by pass a2dp
4700 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4701 bypass_a2dp = true;
4702 } else {
4703 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4704 /* update device to a2dp and don't route as BT returned error
4705 * However it is still possible a2dp routing called because
4706 * of current active device disconnection (like wired headset)
4707 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004708 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004709 pthread_mutex_unlock(&adev->lock);
4710 pthread_mutex_unlock(&out->lock);
4711 goto error;
4712 }
4713 }
4714 }
4715
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004716 // Workaround: If routing to an non existing usb device, fail gracefully
4717 // The routing request will otherwise block during 10 second
4718 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004719 if (is_usb_out_device_type(&new_devices)) {
4720 struct str_parms *parms =
4721 str_parms_create_str(get_usb_device_address(&new_devices));
4722 if (!parms)
4723 goto error;
4724 if ((card = get_alive_usb_card(parms)) >= 0) {
4725 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4726 pthread_mutex_unlock(&adev->lock);
4727 pthread_mutex_unlock(&out->lock);
4728 str_parms_destroy(parms);
4729 ret = -ENOSYS;
4730 goto error;
4731 }
4732 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004733 }
4734
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004735 // Workaround: If routing to an non existing hdmi device, fail gracefully
4736 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4737 (platform_get_edid_info_v2(adev->platform,
4738 out->extconn.cs.controller,
4739 out->extconn.cs.stream) != 0)) {
4740 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4741 pthread_mutex_unlock(&adev->lock);
4742 pthread_mutex_unlock(&out->lock);
4743 ret = -ENOSYS;
4744 goto error;
4745 }
4746
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004747 /*
4748 * select_devices() call below switches all the usecases on the same
4749 * backend to the new device. Refer to check_usecases_codec_backend() in
4750 * the select_devices(). But how do we undo this?
4751 *
4752 * For example, music playback is active on headset (deep-buffer usecase)
4753 * and if we go to ringtones and select a ringtone, low-latency usecase
4754 * will be started on headset+speaker. As we can't enable headset+speaker
4755 * and headset devices at the same time, select_devices() switches the music
4756 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4757 * So when the ringtone playback is completed, how do we undo the same?
4758 *
4759 * We are relying on the out_set_parameters() call on deep-buffer output,
4760 * once the ringtone playback is ended.
4761 * NOTE: We should not check if the current devices are same as new devices.
4762 * Because select_devices() must be called to switch back the music
4763 * playback to headset.
4764 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004765 if (!list_empty(&new_devices)) {
4766 bool same_dev = compare_devices(&out->device_list, &new_devices);
4767 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004768
4769 if (output_drives_call(adev, out)) {
4770 if (!voice_is_call_state_active(adev)) {
4771 if (adev->mode == AUDIO_MODE_IN_CALL) {
4772 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004773 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004774 service_interval =
4775 audio_extn_usb_find_service_interval(true, true /*playback*/);
4776 audio_extn_usb_set_service_interval(true /*playback*/,
4777 service_interval,
4778 &reconfig);
4779 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4780 }
4781 ret = voice_start_call(adev);
4782 }
4783 } else {
4784 adev->current_call_output = out;
4785 voice_update_devices_for_all_voice_usecases(adev);
4786 }
4787 }
4788
4789 if (!out->standby) {
4790 if (!same_dev) {
4791 ALOGV("update routing change");
4792 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4793 adev->perf_lock_opts,
4794 adev->perf_lock_opts_size);
4795 if (adev->adm_on_routing_change)
4796 adev->adm_on_routing_change(adev->adm_data,
4797 out->handle);
4798 }
4799 if (!bypass_a2dp) {
4800 select_devices(adev, out->usecase);
4801 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004802 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4803 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004804 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004805 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004806 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004807 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004808 }
4809
4810 if (!same_dev) {
4811 // on device switch force swap, lower functions will make sure
4812 // to check if swap is allowed or not.
4813 platform_set_swap_channels(adev, true);
4814 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4815 }
4816 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4817 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004818 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004819 pthread_mutex_lock(&out->compr_mute_lock);
4820 out->a2dp_compress_mute = false;
4821 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4822 pthread_mutex_unlock(&out->compr_mute_lock);
4823 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4824 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4825 }
4826 }
4827 }
4828
4829 pthread_mutex_unlock(&adev->lock);
4830 pthread_mutex_unlock(&out->lock);
4831
4832 /*handles device and call state changes*/
4833 audio_extn_extspk_update(adev->extspk);
4834
4835error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004836 ALOGV("%s: exit: code(%d)", __func__, ret);
4837 return ret;
4838}
4839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004840static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4841{
4842 struct stream_out *out = (struct stream_out *)stream;
4843 struct audio_device *adev = out->dev;
4844 struct str_parms *parms;
4845 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004846 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004847 int ext_controller = -1;
4848 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004849
sangwoobc677242013-08-08 16:53:43 +09004850 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004851 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004852 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304853 if (!parms)
4854 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004855
4856 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4857 &ext_stream);
4858 if (err >= 0) {
4859 out->extconn.cs.controller = ext_controller;
4860 out->extconn.cs.stream = ext_stream;
4861 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4862 use_case_table[out->usecase], out->extconn.cs.controller,
4863 out->extconn.cs.stream);
4864 }
4865
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004866 if (out == adev->primary_output) {
4867 pthread_mutex_lock(&adev->lock);
4868 audio_extn_set_parameters(adev, parms);
4869 pthread_mutex_unlock(&adev->lock);
4870 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004871 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004872 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004873 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004874
4875 audio_extn_dts_create_state_notifier_node(out->usecase);
4876 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4877 popcount(out->channel_mask),
4878 out->playback_started);
4879
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004880 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004881 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004882
Surendar Karkaf51b5842018-04-26 11:28:38 +05304883 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4884 sizeof(value));
4885 if (err >= 0) {
4886 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4887 audio_extn_send_dual_mono_mixing_coefficients(out);
4888 }
4889
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304890 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4891 if (err >= 0) {
4892 strlcpy(out->profile, value, sizeof(out->profile));
4893 ALOGV("updating stream profile with value '%s'", out->profile);
4894 lock_output_stream(out);
4895 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4896 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004897 &out->device_list, out->flags,
4898 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304899 out->sample_rate, out->bit_width,
4900 out->channel_mask, out->profile,
4901 &out->app_type_cfg);
4902 pthread_mutex_unlock(&out->lock);
4903 }
4904
Alexy Joseph98988832017-01-13 14:56:59 -08004905 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004906 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4907 // and vendor.audio.hal.output.suspend.supported is set to true
4908 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004909 //check suspend parameter only for low latency and if the property
4910 //is enabled
4911 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4912 ALOGI("%s: got suspend_playback %s", __func__, value);
4913 lock_output_stream(out);
4914 if (!strncmp(value, "false", 5)) {
4915 //suspend_playback=false is supposed to set QOS value back to 75%
4916 //the mixer control sent with value Enable will achieve that
4917 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4918 } else if (!strncmp (value, "true", 4)) {
4919 //suspend_playback=true is supposed to remove QOS value
4920 //resetting the mixer control will set the default value
4921 //for the mixer control which is Disable and this removes the QOS vote
4922 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4923 } else {
4924 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4925 " got %s", __func__, value);
4926 ret = -1;
4927 }
4928
4929 if (ret != 0) {
4930 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4931 __func__, out->pm_qos_mixer_path, ret);
4932 }
4933
4934 pthread_mutex_unlock(&out->lock);
4935 }
4936 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004937
Alexy Joseph98988832017-01-13 14:56:59 -08004938 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004939 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304940error:
Eric Laurent994a6932013-07-17 11:51:42 -07004941 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004942 return ret;
4943}
4944
Paul McLeana50b7332018-12-17 08:24:21 -07004945static int in_set_microphone_direction(const struct audio_stream_in *stream,
4946 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004947 struct stream_in *in = (struct stream_in *)stream;
4948
4949 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4950
4951 in->direction = dir;
4952
4953 if (in->standby)
4954 return 0;
4955
4956 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004957}
4958
4959static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004960 struct stream_in *in = (struct stream_in *)stream;
4961
4962 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4963
4964 if (zoom > 1.0 || zoom < -1.0)
4965 return -EINVAL;
4966
4967 in->zoom = zoom;
4968
4969 if (in->standby)
4970 return 0;
4971
4972 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004973}
4974
4975
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004976static bool stream_get_parameter_channels(struct str_parms *query,
4977 struct str_parms *reply,
4978 audio_channel_mask_t *supported_channel_masks) {
4979 int ret = -1;
4980 char value[512];
4981 bool first = true;
4982 size_t i, j;
4983
4984 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4985 ret = 0;
4986 value[0] = '\0';
4987 i = 0;
4988 while (supported_channel_masks[i] != 0) {
4989 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4990 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4991 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304992 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004993
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304994 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004995 first = false;
4996 break;
4997 }
4998 }
4999 i++;
5000 }
5001 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5002 }
5003 return ret == 0;
5004}
5005
5006static bool stream_get_parameter_formats(struct str_parms *query,
5007 struct str_parms *reply,
5008 audio_format_t *supported_formats) {
5009 int ret = -1;
5010 char value[256];
5011 size_t i, j;
5012 bool first = true;
5013
5014 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5015 ret = 0;
5016 value[0] = '\0';
5017 i = 0;
5018 while (supported_formats[i] != 0) {
5019 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5020 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5021 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305022 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005023 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305024 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005025 first = false;
5026 break;
5027 }
5028 }
5029 i++;
5030 }
5031 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5032 }
5033 return ret == 0;
5034}
5035
5036static bool stream_get_parameter_rates(struct str_parms *query,
5037 struct str_parms *reply,
5038 uint32_t *supported_sample_rates) {
5039
5040 int i;
5041 char value[256];
5042 int ret = -1;
5043 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5044 ret = 0;
5045 value[0] = '\0';
5046 i=0;
5047 int cursor = 0;
5048 while (supported_sample_rates[i]) {
5049 int avail = sizeof(value) - cursor;
5050 ret = snprintf(value + cursor, avail, "%s%d",
5051 cursor > 0 ? "|" : "",
5052 supported_sample_rates[i]);
5053 if (ret < 0 || ret >= avail) {
5054 // if cursor is at the last element of the array
5055 // overwrite with \0 is duplicate work as
5056 // snprintf already put a \0 in place.
5057 // else
5058 // we had space to write the '|' at value[cursor]
5059 // (which will be overwritten) or no space to fill
5060 // the first element (=> cursor == 0)
5061 value[cursor] = '\0';
5062 break;
5063 }
5064 cursor += ret;
5065 ++i;
5066 }
5067 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5068 value);
5069 }
5070 return ret >= 0;
5071}
5072
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005073static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5074{
5075 struct stream_out *out = (struct stream_out *)stream;
5076 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005077 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005078 char value[256];
5079 struct str_parms *reply = str_parms_create();
5080 size_t i, j;
5081 int ret;
5082 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005083
5084 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005085 if (reply) {
5086 str_parms_destroy(reply);
5087 }
5088 if (query) {
5089 str_parms_destroy(query);
5090 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005091 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5092 return NULL;
5093 }
5094
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005095 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005096 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5097 if (ret >= 0) {
5098 value[0] = '\0';
5099 i = 0;
5100 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005101 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5102 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005104 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005105 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005106 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005107 first = false;
5108 break;
5109 }
5110 }
5111 i++;
5112 }
5113 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5114 str = str_parms_to_str(reply);
5115 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005116 voice_extn_out_get_parameters(out, query, reply);
5117 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005118 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005119
Alexy Joseph62142aa2015-11-16 15:10:34 -08005120
5121 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5122 if (ret >= 0) {
5123 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305124 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5125 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005126 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305127 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005128 } else {
5129 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305130 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005131 }
5132 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005133 if (str)
5134 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005135 str = str_parms_to_str(reply);
5136 }
5137
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005138 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5139 if (ret >= 0) {
5140 value[0] = '\0';
5141 i = 0;
5142 first = true;
5143 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005144 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5145 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005146 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005147 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005148 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005149 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005150 first = false;
5151 break;
5152 }
5153 }
5154 i++;
5155 }
5156 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005157 if (str)
5158 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005159 str = str_parms_to_str(reply);
5160 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005161
5162 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5163 if (ret >= 0) {
5164 value[0] = '\0';
5165 i = 0;
5166 first = true;
5167 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005168 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5169 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005170 if (!first) {
5171 strlcat(value, "|", sizeof(value));
5172 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005173 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005174 first = false;
5175 break;
5176 }
5177 }
5178 i++;
5179 }
5180 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5181 if (str)
5182 free(str);
5183 str = str_parms_to_str(reply);
5184 }
5185
Alexy Joseph98988832017-01-13 14:56:59 -08005186 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5187 //only low latency track supports suspend_resume
5188 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005189 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005190 if (str)
5191 free(str);
5192 str = str_parms_to_str(reply);
5193 }
5194
5195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005196 str_parms_destroy(query);
5197 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005198 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005199 return str;
5200}
5201
5202static uint32_t out_get_latency(const struct audio_stream_out *stream)
5203{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005204 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005205 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005206 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005207
Alexy Josephaa54c872014-12-03 02:46:47 -08005208 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305209 lock_output_stream(out);
5210 latency = audio_extn_utils_compress_get_dsp_latency(out);
5211 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005212 } else if ((out->realtime) ||
5213 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005214 // since the buffer won't be filled up faster than realtime,
5215 // return a smaller number
5216 if (out->config.rate)
5217 period_ms = (out->af_period_multiplier * out->config.period_size *
5218 1000) / (out->config.rate);
5219 else
5220 period_ms = 0;
5221 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005222 } else {
5223 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005224 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005225 }
5226
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005227 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005228 latency += audio_extn_a2dp_get_encoder_latency();
5229
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305230 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005231 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005232}
5233
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305234static float AmpToDb(float amplification)
5235{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305236 float db = DSD_VOLUME_MIN_DB;
5237 if (amplification > 0) {
5238 db = 20 * log10(amplification);
5239 if(db < DSD_VOLUME_MIN_DB)
5240 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305241 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305242 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305243}
5244
Arun Mirpuri5d170872019-03-26 13:21:31 -07005245static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5246 float right)
5247{
5248 struct stream_out *out = (struct stream_out *)stream;
5249 long volume = 0;
5250 char mixer_ctl_name[128] = "";
5251 struct audio_device *adev = out->dev;
5252 struct mixer_ctl *ctl = NULL;
5253 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5254 PCM_PLAYBACK);
5255
5256 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5257 "Playback %d Volume", pcm_device_id);
5258 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5259 if (!ctl) {
5260 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5261 __func__, mixer_ctl_name);
5262 return -EINVAL;
5263 }
5264 if (left != right)
5265 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5266 __func__, left, right);
5267 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5268 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5269 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5270 __func__, mixer_ctl_name, volume);
5271 return -EINVAL;
5272 }
5273 return 0;
5274}
5275
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305276static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5277 float right)
5278{
5279 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305280 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305281 char mixer_ctl_name[128];
5282 struct audio_device *adev = out->dev;
5283 struct mixer_ctl *ctl;
5284 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5285 PCM_PLAYBACK);
5286
5287 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5288 "Compress Playback %d Volume", pcm_device_id);
5289 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5290 if (!ctl) {
5291 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5292 __func__, mixer_ctl_name);
5293 return -EINVAL;
5294 }
5295 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5296 __func__, mixer_ctl_name, left, right);
5297 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5298 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5299 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5300
5301 return 0;
5302}
5303
Zhou Song2b8f28f2017-09-11 10:51:38 +08005304static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5305 float right)
5306{
5307 struct stream_out *out = (struct stream_out *)stream;
5308 char mixer_ctl_name[] = "App Type Gain";
5309 struct audio_device *adev = out->dev;
5310 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305311 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005312
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005313 if (!is_valid_volume(left, right)) {
5314 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5315 __func__, left, right);
5316 return -EINVAL;
5317 }
5318
Zhou Song2b8f28f2017-09-11 10:51:38 +08005319 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5320 if (!ctl) {
5321 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5322 __func__, mixer_ctl_name);
5323 return -EINVAL;
5324 }
5325
5326 set_values[0] = 0; //0: Rx Session 1:Tx Session
5327 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305328 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5329 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005330
5331 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5332 return 0;
5333}
5334
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305335static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5336 float right)
5337{
5338 struct stream_out *out = (struct stream_out *)stream;
5339 /* Volume control for pcm playback */
5340 if (left != right) {
5341 return -EINVAL;
5342 } else {
5343 char mixer_ctl_name[128];
5344 struct audio_device *adev = out->dev;
5345 struct mixer_ctl *ctl;
5346 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5347 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5348 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5349 if (!ctl) {
5350 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5351 return -EINVAL;
5352 }
5353
5354 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5355 int ret = mixer_ctl_set_value(ctl, 0, volume);
5356 if (ret < 0) {
5357 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5358 return -EINVAL;
5359 }
5360
5361 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5362
5363 return 0;
5364 }
5365}
5366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005367static int out_set_volume(struct audio_stream_out *stream, float left,
5368 float right)
5369{
Eric Laurenta9024de2013-04-04 09:19:12 -07005370 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005371 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305372 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005373
Arun Mirpuri5d170872019-03-26 13:21:31 -07005374 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005375 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5376 /* only take left channel into account: the API is for stereo anyway */
5377 out->muted = (left == 0.0f);
5378 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005379 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305380 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005381 /*
5382 * Set mute or umute on HDMI passthrough stream.
5383 * Only take left channel into account.
5384 * Mute is 0 and unmute 1
5385 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305386 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305387 } else if (out->format == AUDIO_FORMAT_DSD){
5388 char mixer_ctl_name[128] = "DSD Volume";
5389 struct audio_device *adev = out->dev;
5390 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5391
5392 if (!ctl) {
5393 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5394 __func__, mixer_ctl_name);
5395 return -EINVAL;
5396 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305397 volume[0] = (long)(AmpToDb(left));
5398 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305399 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5400 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005401 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005402 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005403 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5404 struct listnode *node = NULL;
5405 list_for_each(node, &adev->active_outputs_list) {
5406 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5407 streams_output_ctxt_t,
5408 list);
5409 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5410 out->volume_l = out_ctxt->output->volume_l;
5411 out->volume_r = out_ctxt->output->volume_r;
5412 }
5413 }
5414 if (!out->a2dp_compress_mute) {
5415 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5416 }
5417 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005418 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305419 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005420 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305421 if (!out->a2dp_compress_mute)
5422 ret = out_set_compr_volume(stream, left, right);
5423 out->volume_l = left;
5424 out->volume_r = right;
5425 pthread_mutex_unlock(&out->compr_mute_lock);
5426 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005427 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005428 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005429 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5430 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5431 if (!out->standby) {
5432 audio_extn_utils_send_app_type_gain(out->dev,
5433 out->app_type_cfg.app_type,
5434 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005435 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005436 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005437 out->volume_l = left;
5438 out->volume_r = right;
5439 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005440 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5441 ALOGV("%s: MMAP set volume called", __func__);
5442 if (!out->standby)
5443 ret = out_set_mmap_volume(stream, left, right);
5444 out->volume_l = left;
5445 out->volume_r = right;
5446 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305447 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305448 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5449 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305450 /* Volume control for pcm playback */
5451 if (!out->standby)
5452 ret = out_set_pcm_volume(stream, left, right);
5453 else
5454 out->apply_volume = true;
5455
5456 out->volume_l = left;
5457 out->volume_r = right;
5458 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005459 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5460 ALOGV("%s: bus device set volume called", __func__);
5461 if (!out->standby)
5462 ret = out_set_pcm_volume(stream, left, right);
5463 out->volume_l = left;
5464 out->volume_r = right;
5465 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005466 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005468 return -ENOSYS;
5469}
5470
Zhou Songc9672822017-08-16 16:01:39 +08005471static void update_frames_written(struct stream_out *out, size_t bytes)
5472{
5473 size_t bpf = 0;
5474
5475 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5476 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5477 bpf = 1;
5478 else if (!is_offload_usecase(out->usecase))
5479 bpf = audio_bytes_per_sample(out->format) *
5480 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005481
5482 pthread_mutex_lock(&out->position_query_lock);
5483 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005484 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005485 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5486 }
5487 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005488}
5489
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005490int split_and_write_audio_haptic_data(struct stream_out *out,
5491 const void *buffer, size_t bytes_to_write)
5492{
5493 struct audio_device *adev = out->dev;
5494
5495 int ret = 0;
5496 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5497 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5498 size_t frame_size = channel_count * bytes_per_sample;
5499 size_t frame_count = bytes_to_write / frame_size;
5500
5501 bool force_haptic_path =
5502 property_get_bool("vendor.audio.test_haptic", false);
5503
5504 // extract Haptics data from Audio buffer
5505 bool alloc_haptic_buffer = false;
5506 int haptic_channel_count = adev->haptics_config.channels;
5507 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5508 size_t audio_frame_size = frame_size - haptic_frame_size;
5509 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5510
5511 if (adev->haptic_buffer == NULL) {
5512 alloc_haptic_buffer = true;
5513 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5514 free(adev->haptic_buffer);
5515 adev->haptic_buffer_size = 0;
5516 alloc_haptic_buffer = true;
5517 }
5518
5519 if (alloc_haptic_buffer) {
5520 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005521 if(adev->haptic_buffer == NULL) {
5522 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5523 return -ENOMEM;
5524 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005525 adev->haptic_buffer_size = total_haptic_buffer_size;
5526 }
5527
5528 size_t src_index = 0, aud_index = 0, hap_index = 0;
5529 uint8_t *audio_buffer = (uint8_t *)buffer;
5530 uint8_t *haptic_buffer = adev->haptic_buffer;
5531
5532 // This is required for testing only. This works for stereo data only.
5533 // One channel is fed to audio stream and other to haptic stream for testing.
5534 if (force_haptic_path)
5535 audio_frame_size = haptic_frame_size = bytes_per_sample;
5536
5537 for (size_t i = 0; i < frame_count; i++) {
5538 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5539 audio_frame_size);
5540 aud_index += audio_frame_size;
5541 src_index += audio_frame_size;
5542
5543 if (adev->haptic_pcm)
5544 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5545 haptic_frame_size);
5546 hap_index += haptic_frame_size;
5547 src_index += haptic_frame_size;
5548
5549 // This is required for testing only.
5550 // Discard haptic channel data.
5551 if (force_haptic_path)
5552 src_index += haptic_frame_size;
5553 }
5554
5555 // write to audio pipeline
5556 ret = pcm_write(out->pcm, (void *)audio_buffer,
5557 frame_count * audio_frame_size);
5558
5559 // write to haptics pipeline
5560 if (adev->haptic_pcm)
5561 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5562 frame_count * haptic_frame_size);
5563
5564 return ret;
5565}
5566
Aalique Grahame22e49102018-12-18 14:23:57 -08005567#ifdef NO_AUDIO_OUT
5568static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5569 const void *buffer __unused, size_t bytes)
5570{
5571 struct stream_out *out = (struct stream_out *)stream;
5572
5573 /* No Output device supported other than BT for playback.
5574 * Sleep for the amount of buffer duration
5575 */
5576 lock_output_stream(out);
5577 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5578 (const struct audio_stream_out *)&out->stream) /
5579 out_get_sample_rate(&out->stream.common));
5580 pthread_mutex_unlock(&out->lock);
5581 return bytes;
5582}
5583#endif
5584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005585static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5586 size_t bytes)
5587{
5588 struct stream_out *out = (struct stream_out *)stream;
5589 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005590 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305591 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005592 const size_t frame_size = audio_stream_out_frame_size(stream);
5593 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305594 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005595 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005596
Haynes Mathew George380745d2017-10-04 15:27:45 -07005597 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005598 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305599
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305600 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005601
Dhananjay Kumarac341582017-02-23 23:42:25 +05305602 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305603 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305604 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5605 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005606 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305607 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305608 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305609 ALOGD(" %s: sound card is not active/SSR state", __func__);
5610 ret= -EIO;
5611 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305612 }
5613 }
5614
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305615 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305616 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305617 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305618 goto exit;
5619 }
5620
Haynes Mathew George16081042017-05-31 17:16:49 -07005621 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5622 ret = -EINVAL;
5623 goto exit;
5624 }
5625
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005626 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305627 !out->is_iec61937_info_available) {
5628
5629 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5630 out->is_iec61937_info_available = true;
5631 } else if (audio_extn_passthru_is_enabled()) {
5632 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305633 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305634
5635 if((out->format == AUDIO_FORMAT_DTS) ||
5636 (out->format == AUDIO_FORMAT_DTS_HD)) {
5637 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5638 buffer, bytes);
5639 if (ret) {
5640 if (ret != -ENOSYS) {
5641 out->is_iec61937_info_available = false;
5642 ALOGD("iec61937 transmission info not yet updated retry");
5643 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305644 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305645 /* if stream has started and after that there is
5646 * stream config change (iec transmission config)
5647 * then trigger select_device to update backend configuration.
5648 */
5649 out->stream_config_changed = true;
5650 pthread_mutex_lock(&adev->lock);
5651 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305652 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005653 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305654 ret = -EINVAL;
5655 goto exit;
5656 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305657 pthread_mutex_unlock(&adev->lock);
5658 out->stream_config_changed = false;
5659 out->is_iec61937_info_available = true;
5660 }
5661 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305662
Meng Wang4c32fb42020-01-16 17:57:11 +08005663#ifdef AUDIO_GKI_ENABLED
5664 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5665 compr_passthr = out->compr_config.codec->reserved[0];
5666#else
5667 compr_passthr = out->compr_config.codec->compr_passthr;
5668#endif
5669
Garmond Leung317cbf12017-09-13 16:20:50 -07005670 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005671 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305672 (out->is_iec61937_info_available == true)) {
5673 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5674 ret = -EINVAL;
5675 goto exit;
5676 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305677 }
5678 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305679
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005680 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005681 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005682 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5683 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305684 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305685 ret = -EIO;
5686 goto exit;
5687 }
5688 }
5689 }
5690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005691 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005692 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005693 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005694 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5695 ret = voice_extn_compress_voip_start_output_stream(out);
5696 else
5697 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005698 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005699 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005700 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005701 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005702 goto exit;
5703 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305704 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005705 if (last_known_cal_step != -1) {
5706 ALOGD("%s: retry previous failed cal level set", __func__);
5707 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305708 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005709 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305710
5711 if ((out->is_iec61937_info_available == true) &&
5712 (audio_extn_passthru_is_passthrough_stream(out))&&
5713 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5714 ret = -EINVAL;
5715 goto exit;
5716 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305717 if (out->set_dual_mono)
5718 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005719 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005720
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005721 if (adev->is_channel_status_set == false &&
5722 compare_device_type(&out->device_list,
5723 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005724 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305725 adev->is_channel_status_set = true;
5726 }
5727
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305728 if ((adev->use_old_pspd_mix_ctrl == true) &&
5729 (out->pspd_coeff_sent == false)) {
5730 /*
5731 * Need to resend pspd coefficients after stream started for
5732 * older kernel version as it does not save the coefficients
5733 * and also stream has to be started for coeff to apply.
5734 */
5735 usecase = get_usecase_from_list(adev, out->usecase);
5736 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305737 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305738 out->pspd_coeff_sent = true;
5739 }
5740 }
5741
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005742 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005743 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005744 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005745 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005746 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5747 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305748 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5749 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005750 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305751 out->send_next_track_params = false;
5752 out->is_compr_metadata_avail = false;
5753 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005754 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305755 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305756 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005757
Ashish Jain83a6cc22016-06-28 14:34:17 +05305758 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305759 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305760 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305761 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005762 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305763 return -EINVAL;
5764 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305765 audio_format_t dst_format = out->hal_op_format;
5766 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305767
Dieter Luecking5d57def2018-09-07 14:23:37 +02005768 /* prevent division-by-zero */
5769 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5770 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5771 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5772 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305773 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005774 ATRACE_END();
5775 return -EINVAL;
5776 }
5777
Ashish Jainf1eaa582016-05-23 20:54:24 +05305778 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5779 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5780
Ashish Jain83a6cc22016-06-28 14:34:17 +05305781 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305782 dst_format,
5783 buffer,
5784 src_format,
5785 frames);
5786
Ashish Jain83a6cc22016-06-28 14:34:17 +05305787 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305788 bytes_to_write);
5789
5790 /*Convert written bytes in audio flinger format*/
5791 if (ret > 0)
5792 ret = ((ret * format_to_bitwidth_table[out->format]) /
5793 format_to_bitwidth_table[dst_format]);
5794 }
5795 } else
5796 ret = compress_write(out->compr, buffer, bytes);
5797
Zhou Songc9672822017-08-16 16:01:39 +08005798 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5799 update_frames_written(out, bytes);
5800
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305801 if (ret < 0)
5802 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005803 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305804 /*msg to cb thread only if non blocking write is enabled*/
5805 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305806 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005807 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305808 } else if (-ENETRESET == ret) {
5809 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305810 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305811 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305812 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005813 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305814 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005815 }
Ashish Jain5106d362016-05-11 19:23:33 +05305816
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305817 /* Call compr start only when non-zero bytes of data is there to be rendered */
5818 if (!out->playback_started && ret > 0) {
5819 int status = compress_start(out->compr);
5820 if (status < 0) {
5821 ret = status;
5822 ALOGE("%s: compr start failed with err %d", __func__, errno);
5823 goto exit;
5824 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005825 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005826 out->playback_started = 1;
5827 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005828
5829 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5830 popcount(out->channel_mask),
5831 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005832 }
5833 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005834 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005835 return ret;
5836 } else {
5837 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005838 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005839 if (out->muted)
5840 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005841 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5842 __func__, frames, frame_size, bytes_to_write);
5843
Aalique Grahame22e49102018-12-18 14:23:57 -08005844 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005845 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5846 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5847 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005848 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5849 int16_t *src = (int16_t *)buffer;
5850 int16_t *dst = (int16_t *)buffer;
5851
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005852 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005853 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005854 "out_write called for %s use case with wrong properties",
5855 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005856
5857 /*
5858 * FIXME: this can be removed once audio flinger mixer supports
5859 * mono output
5860 */
5861
5862 /*
5863 * Code below goes over each frame in the buffer and adds both
5864 * L and R samples and then divides by 2 to convert to mono
5865 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005866 if (channel_count == 2) {
5867 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5868 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5869 }
5870 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005871 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005872 }
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305873 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005874
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005875 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005876
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005877 if (out->config.rate)
5878 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5879 out->config.rate;
5880
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005881 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005882 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5883
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005884 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005885 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005886 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305887 out->convert_buffer != NULL) {
5888
5889 memcpy_by_audio_format(out->convert_buffer,
5890 out->hal_op_format,
5891 buffer,
5892 out->hal_ip_format,
5893 out->config.period_size * out->config.channels);
5894
5895 ret = pcm_write(out->pcm, out->convert_buffer,
5896 (out->config.period_size *
5897 out->config.channels *
5898 format_to_bitwidth_table[out->hal_op_format]));
5899 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305900 /*
5901 * To avoid underrun in DSP when the application is not pumping
5902 * data at required rate, check for the no. of bytes and ignore
5903 * pcm_write if it is less than actual buffer size.
5904 * It is a work around to a change in compress VOIP driver.
5905 */
5906 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5907 bytes < (out->config.period_size * out->config.channels *
5908 audio_bytes_per_sample(out->format))) {
5909 size_t voip_buf_size =
5910 out->config.period_size * out->config.channels *
5911 audio_bytes_per_sample(out->format);
5912 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5913 __func__, bytes, voip_buf_size);
5914 usleep(((uint64_t)voip_buf_size - bytes) *
5915 1000000 / audio_stream_out_frame_size(stream) /
5916 out_get_sample_rate(&out->stream.common));
5917 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005918 } else {
5919 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5920 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5921 else
5922 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5923 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305924 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005925
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005926 release_out_focus(out);
5927
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305928 if (ret < 0)
5929 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005930 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305931 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005932 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005933 }
5934
5935exit:
Zhou Songc9672822017-08-16 16:01:39 +08005936 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305937 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305938 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305939 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005940 pthread_mutex_unlock(&out->lock);
5941
5942 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005943 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005944 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305945 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305946 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305947 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305948 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305949 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305950 out->standby = true;
5951 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305952 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005953 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5954 /* prevent division-by-zero */
5955 uint32_t stream_size = audio_stream_out_frame_size(stream);
5956 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005957
Dieter Luecking5d57def2018-09-07 14:23:37 +02005958 if ((stream_size == 0) || (srate == 0)) {
5959 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5960 ATRACE_END();
5961 return -EINVAL;
5962 }
5963 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5964 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005965 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305966 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005967 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005968 return ret;
5969 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005970 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005971 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005972 return bytes;
5973}
5974
5975static int out_get_render_position(const struct audio_stream_out *stream,
5976 uint32_t *dsp_frames)
5977{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005978 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005979
5980 if (dsp_frames == NULL)
5981 return -EINVAL;
5982
5983 *dsp_frames = 0;
5984 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005985 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305986
5987 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5988 * this operation and adev_close_output_stream(where out gets reset).
5989 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305990 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005991 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305992 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005993 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305994 return 0;
5995 }
5996
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005997 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305998 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305999 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006000 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306001 if (ret < 0)
6002 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006003 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306004 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006005 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306006 if (-ENETRESET == ret) {
6007 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306008 out->card_status = CARD_STATUS_OFFLINE;
6009 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306010 } else if(ret < 0) {
6011 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306012 ret = -EINVAL;
6013 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306014 /*
6015 * Handle corner case where compress session is closed during SSR
6016 * and timestamp is queried
6017 */
6018 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306019 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306020 } else if (out->prev_card_status_offline) {
6021 ALOGE("ERROR: previously sound card was offline,return error");
6022 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306023 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306024 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006025 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306026 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306027 pthread_mutex_unlock(&out->lock);
6028 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006029 } else if (audio_is_linear_pcm(out->format)) {
6030 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006031 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006032 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006033 } else
6034 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006035}
6036
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006037static int out_add_audio_effect(const struct audio_stream *stream __unused,
6038 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006039{
6040 return 0;
6041}
6042
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006043static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6044 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006045{
6046 return 0;
6047}
6048
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006049static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6050 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006051{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306052 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006053}
6054
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006055static int out_get_presentation_position(const struct audio_stream_out *stream,
6056 uint64_t *frames, struct timespec *timestamp)
6057{
6058 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306059 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006060 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006061
Ashish Jain5106d362016-05-11 19:23:33 +05306062 /* below piece of code is not guarded against any lock because audioFliner serializes
6063 * this operation and adev_close_output_stream( where out gets reset).
6064 */
6065 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306066 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006067 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306068 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6069 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6070 return 0;
6071 }
6072
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006073 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006074
Ashish Jain5106d362016-05-11 19:23:33 +05306075 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6076 ret = compress_get_tstamp(out->compr, &dsp_frames,
6077 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006078 // Adjustment accounts for A2dp encoder latency with offload usecases
6079 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006080 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006081 unsigned long offset =
6082 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6083 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6084 }
Ashish Jain5106d362016-05-11 19:23:33 +05306085 ALOGVV("%s rendered frames %ld sample_rate %d",
6086 __func__, dsp_frames, out->sample_rate);
6087 *frames = dsp_frames;
6088 if (ret < 0)
6089 ret = -errno;
6090 if (-ENETRESET == ret) {
6091 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306092 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306093 ret = -EINVAL;
6094 } else
6095 ret = 0;
6096 /* this is the best we can do */
6097 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006098 } else {
6099 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006100 unsigned int avail;
6101 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
6102 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
George Gao62ebc722019-07-29 16:29:44 -07006103
6104 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006105 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006106
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006107 frames_temp = (kernel_buffer_size > avail) ? (kernel_buffer_size - avail) : 0;
6108 if (out->written >= frames_temp)
6109 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006110
Weiyin Jiangd4633762018-03-16 12:05:03 +08006111 // This adjustment accounts for buffering after app processor.
6112 // It is based on estimated DSP latency per use case, rather than exact.
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006113 frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL;
6114 if (signed_frames >= frames_temp)
6115 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006116
Weiyin Jiangd4633762018-03-16 12:05:03 +08006117 // Adjustment accounts for A2dp encoder latency with non offload usecases
6118 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006119 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006120 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6121 if (signed_frames >= frames_temp)
6122 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006123 }
6124
6125 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006126 *frames = signed_frames;
6127 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006128 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306129 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306130 *frames = out->written;
6131 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306132 if (is_offload_usecase(out->usecase))
6133 ret = -EINVAL;
6134 else
6135 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006136 }
6137 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006138 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006139 return ret;
6140}
6141
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006142static int out_set_callback(struct audio_stream_out *stream,
6143 stream_callback_t callback, void *cookie)
6144{
6145 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006146 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006147
6148 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006149 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006150 out->client_callback = callback;
6151 out->client_cookie = cookie;
6152 if (out->adsp_hdlr_stream_handle) {
6153 ret = audio_extn_adsp_hdlr_stream_set_callback(
6154 out->adsp_hdlr_stream_handle,
6155 callback,
6156 cookie);
6157 if (ret)
6158 ALOGW("%s:adsp hdlr callback registration failed %d",
6159 __func__, ret);
6160 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006161 pthread_mutex_unlock(&out->lock);
6162 return 0;
6163}
6164
6165static int out_pause(struct audio_stream_out* stream)
6166{
6167 struct stream_out *out = (struct stream_out *)stream;
6168 int status = -ENOSYS;
6169 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006170 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006171 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006172 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006173 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306174 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306175 status = compress_pause(out->compr);
6176
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006177 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006178
Mingming Yin21854652016-04-13 11:54:02 -07006179 if (audio_extn_passthru_is_active()) {
6180 ALOGV("offload use case, pause passthru");
6181 audio_extn_passthru_on_pause(out);
6182 }
6183
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306184 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006185 audio_extn_dts_notify_playback_state(out->usecase, 0,
6186 out->sample_rate, popcount(out->channel_mask),
6187 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006188 }
6189 pthread_mutex_unlock(&out->lock);
6190 }
6191 return status;
6192}
6193
6194static int out_resume(struct audio_stream_out* stream)
6195{
6196 struct stream_out *out = (struct stream_out *)stream;
6197 int status = -ENOSYS;
6198 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006199 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006200 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006201 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006202 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006203 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306204 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306205 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006206 }
6207 if (!status) {
6208 out->offload_state = OFFLOAD_STATE_PLAYING;
6209 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306210 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006211 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6212 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006213 }
6214 pthread_mutex_unlock(&out->lock);
6215 }
6216 return status;
6217}
6218
6219static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6220{
6221 struct stream_out *out = (struct stream_out *)stream;
6222 int status = -ENOSYS;
6223 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006224 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006225 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006226 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6227 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6228 else
6229 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6230 pthread_mutex_unlock(&out->lock);
6231 }
6232 return status;
6233}
6234
6235static int out_flush(struct audio_stream_out* stream)
6236{
6237 struct stream_out *out = (struct stream_out *)stream;
6238 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006239 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006240 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006241 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006242 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6243 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006244 } else {
6245 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6246 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006247 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006248 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006249 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006250 return 0;
6251 }
6252 return -ENOSYS;
6253}
6254
Haynes Mathew George16081042017-05-31 17:16:49 -07006255static int out_stop(const struct audio_stream_out* stream)
6256{
6257 struct stream_out *out = (struct stream_out *)stream;
6258 struct audio_device *adev = out->dev;
6259 int ret = -ENOSYS;
6260
6261 ALOGV("%s", __func__);
6262 pthread_mutex_lock(&adev->lock);
6263 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6264 out->playback_started && out->pcm != NULL) {
6265 pcm_stop(out->pcm);
6266 ret = stop_output_stream(out);
6267 out->playback_started = false;
6268 }
6269 pthread_mutex_unlock(&adev->lock);
6270 return ret;
6271}
6272
6273static int out_start(const struct audio_stream_out* stream)
6274{
6275 struct stream_out *out = (struct stream_out *)stream;
6276 struct audio_device *adev = out->dev;
6277 int ret = -ENOSYS;
6278
6279 ALOGV("%s", __func__);
6280 pthread_mutex_lock(&adev->lock);
6281 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6282 !out->playback_started && out->pcm != NULL) {
6283 ret = start_output_stream(out);
6284 if (ret == 0) {
6285 out->playback_started = true;
6286 }
6287 }
6288 pthread_mutex_unlock(&adev->lock);
6289 return ret;
6290}
6291
6292/*
6293 * Modify config->period_count based on min_size_frames
6294 */
6295static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6296{
6297 int periodCountRequested = (min_size_frames + config->period_size - 1)
6298 / config->period_size;
6299 int periodCount = MMAP_PERIOD_COUNT_MIN;
6300
6301 ALOGV("%s original config.period_size = %d config.period_count = %d",
6302 __func__, config->period_size, config->period_count);
6303
6304 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6305 periodCount *= 2;
6306 }
6307 config->period_count = periodCount;
6308
6309 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6310}
6311
Phil Burkfe17efd2019-03-25 10:23:35 -07006312// Read offset for the positional timestamp from a persistent vendor property.
6313// This is to workaround apparent inaccuracies in the timing information that
6314// is used by the AAudio timing model. The inaccuracies can cause glitches.
6315static int64_t get_mmap_out_time_offset() {
6316 const int32_t kDefaultOffsetMicros = 0;
6317 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006318 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006319 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6320 return mmap_time_offset_micros * (int64_t)1000;
6321}
6322
Haynes Mathew George16081042017-05-31 17:16:49 -07006323static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6324 int32_t min_size_frames,
6325 struct audio_mmap_buffer_info *info)
6326{
6327 struct stream_out *out = (struct stream_out *)stream;
6328 struct audio_device *adev = out->dev;
6329 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006330 unsigned int offset1 = 0;
6331 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006332 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006333 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006334 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006335
Arun Mirpuri5d170872019-03-26 13:21:31 -07006336 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306337 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006338 pthread_mutex_lock(&adev->lock);
6339
Sharad Sanglec6f32552018-05-04 16:15:38 +05306340 if (CARD_STATUS_OFFLINE == out->card_status ||
6341 CARD_STATUS_OFFLINE == adev->card_status) {
6342 ALOGW("out->card_status or adev->card_status offline, try again");
6343 ret = -EIO;
6344 goto exit;
6345 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006346 if (info == NULL || min_size_frames == 0) {
6347 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6348 ret = -EINVAL;
6349 goto exit;
6350 }
6351 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6352 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6353 ret = -ENOSYS;
6354 goto exit;
6355 }
6356 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6357 if (out->pcm_device_id < 0) {
6358 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6359 __func__, out->pcm_device_id, out->usecase);
6360 ret = -EINVAL;
6361 goto exit;
6362 }
6363
6364 adjust_mmap_period_count(&out->config, min_size_frames);
6365
Arun Mirpuri5d170872019-03-26 13:21:31 -07006366 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006367 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6368 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6369 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306370 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306371 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6372 out->card_status = CARD_STATUS_OFFLINE;
6373 adev->card_status = CARD_STATUS_OFFLINE;
6374 ret = -EIO;
6375 goto exit;
6376 }
6377
Haynes Mathew George16081042017-05-31 17:16:49 -07006378 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6379 step = "open";
6380 ret = -ENODEV;
6381 goto exit;
6382 }
6383 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6384 if (ret < 0) {
6385 step = "begin";
6386 goto exit;
6387 }
6388 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006389 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006390 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006391 ret = platform_get_mmap_data_fd(adev->platform,
6392 out->pcm_device_id, 0 /*playback*/,
6393 &info->shared_memory_fd,
6394 &mmap_size);
6395 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006396 // Fall back to non exclusive mode
6397 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6398 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006399 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6400 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6401
Arun Mirpuri5d170872019-03-26 13:21:31 -07006402 if (mmap_size < buffer_size) {
6403 step = "mmap";
6404 goto exit;
6405 }
6406 // FIXME: indicate exclusive mode support by returning a negative buffer size
6407 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006408 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006409 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006410 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006411
6412 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6413 if (ret < 0) {
6414 step = "commit";
6415 goto exit;
6416 }
6417
Phil Burkfe17efd2019-03-25 10:23:35 -07006418 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6419
Haynes Mathew George16081042017-05-31 17:16:49 -07006420 out->standby = false;
6421 ret = 0;
6422
Arun Mirpuri5d170872019-03-26 13:21:31 -07006423 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006424 __func__, info->shared_memory_address, info->buffer_size_frames);
6425
6426exit:
6427 if (ret != 0) {
6428 if (out->pcm == NULL) {
6429 ALOGE("%s: %s - %d", __func__, step, ret);
6430 } else {
6431 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6432 pcm_close(out->pcm);
6433 out->pcm = NULL;
6434 }
6435 }
6436 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306437 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006438 return ret;
6439}
6440
6441static int out_get_mmap_position(const struct audio_stream_out *stream,
6442 struct audio_mmap_position *position)
6443{
6444 struct stream_out *out = (struct stream_out *)stream;
6445 ALOGVV("%s", __func__);
6446 if (position == NULL) {
6447 return -EINVAL;
6448 }
6449 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006450 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006451 return -ENOSYS;
6452 }
6453 if (out->pcm == NULL) {
6454 return -ENOSYS;
6455 }
6456
6457 struct timespec ts = { 0, 0 };
6458 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6459 if (ret < 0) {
6460 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6461 return ret;
6462 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006463 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6464 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006465 return 0;
6466}
6467
6468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006469/** audio_stream_in implementation **/
6470static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6471{
6472 struct stream_in *in = (struct stream_in *)stream;
6473
6474 return in->config.rate;
6475}
6476
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006477static int in_set_sample_rate(struct audio_stream *stream __unused,
6478 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006479{
6480 return -ENOSYS;
6481}
6482
6483static size_t in_get_buffer_size(const struct audio_stream *stream)
6484{
6485 struct stream_in *in = (struct stream_in *)stream;
6486
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006487 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6488 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006489 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6490 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306491 else if(audio_extn_cin_attached_usecase(in->usecase))
6492 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006493
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006494 return in->config.period_size * in->af_period_multiplier *
6495 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006496}
6497
6498static uint32_t in_get_channels(const struct audio_stream *stream)
6499{
6500 struct stream_in *in = (struct stream_in *)stream;
6501
6502 return in->channel_mask;
6503}
6504
6505static audio_format_t in_get_format(const struct audio_stream *stream)
6506{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006507 struct stream_in *in = (struct stream_in *)stream;
6508
6509 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006510}
6511
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006512static int in_set_format(struct audio_stream *stream __unused,
6513 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006514{
6515 return -ENOSYS;
6516}
6517
6518static int in_standby(struct audio_stream *stream)
6519{
6520 struct stream_in *in = (struct stream_in *)stream;
6521 struct audio_device *adev = in->dev;
6522 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306523 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6524 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006525 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306526
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006527 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006528 if (!in->standby && in->is_st_session) {
6529 ALOGD("%s: sound trigger pcm stop lab", __func__);
6530 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006531 if (adev->num_va_sessions > 0)
6532 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006533 in->standby = 1;
6534 }
6535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006536 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006537 if (adev->adm_deregister_stream)
6538 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6539
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006540 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006541 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006542 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006543 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006544 voice_extn_compress_voip_close_input_stream(stream);
6545 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006546 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6547 do_stop = in->capture_started;
6548 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006549 if (in->mmap_shared_memory_fd >= 0) {
6550 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6551 __func__, in->mmap_shared_memory_fd);
6552 close(in->mmap_shared_memory_fd);
6553 in->mmap_shared_memory_fd = -1;
6554 }
Zhou Songa8895042016-07-05 17:54:22 +08006555 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306556 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05306557 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006558 }
6559
Arun Mirpuri5d170872019-03-26 13:21:31 -07006560 if (in->pcm) {
6561 ATRACE_BEGIN("pcm_in_close");
6562 pcm_close(in->pcm);
6563 ATRACE_END();
6564 in->pcm = NULL;
6565 }
6566
Carter Hsu2e429db2019-05-14 18:50:52 +08006567 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006568 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006569
George Gao3018ede2019-10-23 13:23:00 -07006570 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6571 if (adev->num_va_sessions > 0)
6572 adev->num_va_sessions--;
6573 }
Quinn Malef6050362019-01-30 15:55:40 -08006574
Eric Laurent150dbfe2013-02-27 14:31:02 -08006575 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006576 }
6577 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006578 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006579 return status;
6580}
6581
Aalique Grahame22e49102018-12-18 14:23:57 -08006582static int in_dump(const struct audio_stream *stream,
6583 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006584{
Aalique Grahame22e49102018-12-18 14:23:57 -08006585 struct stream_in *in = (struct stream_in *)stream;
6586
6587 // We try to get the lock for consistency,
6588 // but it isn't necessary for these variables.
6589 // If we're not in standby, we may be blocked on a read.
6590 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6591 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6592 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6593 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6594
6595 if (locked) {
6596 pthread_mutex_unlock(&in->lock);
6597 }
6598
6599 // dump error info
6600 (void)error_log_dump(
6601 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006603 return 0;
6604}
6605
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306606static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6607{
6608 if (!stream || !parms)
6609 return;
6610
6611 struct stream_in *in = (struct stream_in *)stream;
6612 struct audio_device *adev = in->dev;
6613
6614 card_status_t status;
6615 int card;
6616 if (parse_snd_card_status(parms, &card, &status) < 0)
6617 return;
6618
6619 pthread_mutex_lock(&adev->lock);
6620 bool valid_cb = (card == adev->snd_card);
6621 pthread_mutex_unlock(&adev->lock);
6622
6623 if (!valid_cb)
6624 return;
6625
6626 lock_input_stream(in);
6627 if (in->card_status != status)
6628 in->card_status = status;
6629 pthread_mutex_unlock(&in->lock);
6630
6631 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6632 use_case_table[in->usecase],
6633 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6634
6635 // a better solution would be to report error back to AF and let
6636 // it put the stream to standby
6637 if (status == CARD_STATUS_OFFLINE)
6638 in_standby(&in->stream.common);
6639
6640 return;
6641}
6642
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006643int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006644 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006645 audio_source_t source)
6646{
6647 struct audio_device *adev = in->dev;
6648 int ret = 0;
6649
6650 lock_input_stream(in);
6651 pthread_mutex_lock(&adev->lock);
6652
6653 /* no audio source uses val == 0 */
6654 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6655 in->source = source;
6656 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6657 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6658 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6659 (in->config.rate == 8000 || in->config.rate == 16000 ||
6660 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6661 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6662 ret = voice_extn_compress_voip_open_input_stream(in);
6663 if (ret != 0) {
6664 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6665 __func__, ret);
6666 }
6667 }
6668 }
6669
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006670 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6671 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006672 // Workaround: If routing to an non existing usb device, fail gracefully
6673 // The routing request will otherwise block during 10 second
6674 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006675 struct str_parms *usb_addr =
6676 str_parms_create_str(get_usb_device_address(devices));
6677 if (is_usb_in_device_type(devices) && usb_addr &&
6678 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006679 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6680 ret = -ENOSYS;
6681 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006682 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006683 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006684 if (!in->standby && !in->is_st_session) {
6685 ALOGV("update input routing change");
6686 // inform adm before actual routing to prevent glitches.
6687 if (adev->adm_on_routing_change) {
6688 adev->adm_on_routing_change(adev->adm_data,
6689 in->capture_handle);
6690 ret = select_devices(adev, in->usecase);
6691 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6692 adev->adm_routing_changed = true;
6693 }
6694 }
6695 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006696 if (usb_addr)
6697 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006698 }
6699 pthread_mutex_unlock(&adev->lock);
6700 pthread_mutex_unlock(&in->lock);
6701
6702 ALOGD("%s: exit: status(%d)", __func__, ret);
6703 return ret;
6704}
6705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006706static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6707{
6708 struct stream_in *in = (struct stream_in *)stream;
6709 struct audio_device *adev = in->dev;
6710 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006711 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006712 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006713
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306714 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006715 parms = str_parms_create_str(kvpairs);
6716
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306717 if (!parms)
6718 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006719 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006720 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006721
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006722 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6723 if (ret >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306724 strlcpy(in->profile, value, sizeof(in->profile));
6725 ALOGV("updating stream profile with value '%s'", in->profile);
6726 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6727 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006728 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306729 in->sample_rate, in->bit_width,
6730 in->profile, &in->app_type_cfg);
6731 }
6732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006733 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006734 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006735
6736 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306737error:
Eric Laurent994a6932013-07-17 11:51:42 -07006738 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006739 return ret;
6740}
6741
6742static char* in_get_parameters(const struct audio_stream *stream,
6743 const char *keys)
6744{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006745 struct stream_in *in = (struct stream_in *)stream;
6746 struct str_parms *query = str_parms_create_str(keys);
6747 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006748 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006749
6750 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006751 if (reply) {
6752 str_parms_destroy(reply);
6753 }
6754 if (query) {
6755 str_parms_destroy(query);
6756 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006757 ALOGE("in_get_parameters: failed to create query or reply");
6758 return NULL;
6759 }
6760
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006761 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006762
6763 voice_extn_in_get_parameters(in, query, reply);
6764
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006765 stream_get_parameter_channels(query, reply,
6766 &in->supported_channel_masks[0]);
6767 stream_get_parameter_formats(query, reply,
6768 &in->supported_formats[0]);
6769 stream_get_parameter_rates(query, reply,
6770 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006771 str = str_parms_to_str(reply);
6772 str_parms_destroy(query);
6773 str_parms_destroy(reply);
6774
6775 ALOGV("%s: exit: returns - %s", __func__, str);
6776 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006777}
6778
Aalique Grahame22e49102018-12-18 14:23:57 -08006779static int in_set_gain(struct audio_stream_in *stream,
6780 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006781{
Aalique Grahame22e49102018-12-18 14:23:57 -08006782 struct stream_in *in = (struct stream_in *)stream;
6783 char mixer_ctl_name[128];
6784 struct mixer_ctl *ctl;
6785 int ctl_value;
6786
6787 ALOGV("%s: gain %f", __func__, gain);
6788
6789 if (stream == NULL)
6790 return -EINVAL;
6791
6792 /* in_set_gain() only used to silence MMAP capture for now */
6793 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6794 return -ENOSYS;
6795
6796 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6797
6798 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6799 if (!ctl) {
6800 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6801 __func__, mixer_ctl_name);
6802 return -ENOSYS;
6803 }
6804
6805 if (gain < RECORD_GAIN_MIN)
6806 gain = RECORD_GAIN_MIN;
6807 else if (gain > RECORD_GAIN_MAX)
6808 gain = RECORD_GAIN_MAX;
6809 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6810
6811 mixer_ctl_set_value(ctl, 0, ctl_value);
6812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006813 return 0;
6814}
6815
6816static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6817 size_t bytes)
6818{
6819 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306820
6821 if (in == NULL) {
6822 ALOGE("%s: stream_in ptr is NULL", __func__);
6823 return -EINVAL;
6824 }
6825
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006826 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306827 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306828 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006829
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006830 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306831
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006832 if (in->is_st_session) {
6833 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6834 /* Read from sound trigger HAL */
6835 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006836 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006837 if (adev->num_va_sessions < UINT_MAX)
6838 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006839 in->standby = 0;
6840 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006841 pthread_mutex_unlock(&in->lock);
6842 return bytes;
6843 }
6844
Haynes Mathew George16081042017-05-31 17:16:49 -07006845 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6846 ret = -ENOSYS;
6847 goto exit;
6848 }
6849
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006850 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6851 !in->standby && adev->adm_routing_changed) {
6852 ret = -ENOSYS;
6853 goto exit;
6854 }
6855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006856 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006857 pthread_mutex_lock(&adev->lock);
6858 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6859 ret = voice_extn_compress_voip_start_input_stream(in);
6860 else
6861 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006862 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6863 if (adev->num_va_sessions < UINT_MAX)
6864 adev->num_va_sessions++;
6865 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006866 pthread_mutex_unlock(&adev->lock);
6867 if (ret != 0) {
6868 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006869 }
6870 in->standby = 0;
6871 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006872
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306873 /* Avoid read if capture_stopped is set */
6874 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6875 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6876 ret = -EINVAL;
6877 goto exit;
6878 }
6879
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006880 // what's the duration requested by the client?
6881 long ns = 0;
6882
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306883 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006884 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6885 in->config.rate;
6886
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006887 ret = request_in_focus(in, ns);
6888 if (ret != 0)
6889 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006890 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006891
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306892 if (audio_extn_cin_attached_usecase(in->usecase)) {
6893 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6894 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306895 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006896 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306897 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006898 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006899 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006900 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006901 } else if (audio_extn_ffv_get_stream() == in) {
6902 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306903 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006904 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306905 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6906 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6907 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6908 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306909 ret = -EINVAL;
6910 goto exit;
6911 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306912 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306913 ret = -errno;
6914 }
6915 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306916 /* bytes read is always set to bytes for non compress usecases */
6917 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006918 }
6919
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006920 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006922 /*
Quinn Malef6050362019-01-30 15:55:40 -08006923 * Instead of writing zeroes here, we could trust the hardware to always
6924 * provide zeroes when muted. This is also muted with voice recognition
6925 * usecases so that other clients do not have access to voice recognition
6926 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006927 */
Quinn Malef6050362019-01-30 15:55:40 -08006928 if ((ret == 0 && voice_get_mic_mute(adev) &&
6929 !voice_is_in_call_rec_stream(in) &&
Zhou Song62ea0282020-03-22 19:53:01 +08006930 (in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY &&
6931 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY2)) ||
Quinn Malef6050362019-01-30 15:55:40 -08006932 (adev->num_va_sessions &&
6933 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6934 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6935 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006936 memset(buffer, 0, bytes);
6937
6938exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306939 frame_size = audio_stream_in_frame_size(stream);
6940 if (frame_size > 0)
6941 in->frames_read += bytes_read/frame_size;
6942
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006943 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306944 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006945 pthread_mutex_unlock(&in->lock);
6946
6947 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306948 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306949 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306950 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306951 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306952 in->standby = true;
6953 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306954 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6955 bytes_read = bytes;
6956 memset(buffer, 0, bytes);
6957 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006958 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006959 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6960 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006961 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306962 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306963 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006964 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306965 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006966}
6967
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006968static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006969{
6970 return 0;
6971}
6972
Aalique Grahame22e49102018-12-18 14:23:57 -08006973static int in_get_capture_position(const struct audio_stream_in *stream,
6974 int64_t *frames, int64_t *time)
6975{
6976 if (stream == NULL || frames == NULL || time == NULL) {
6977 return -EINVAL;
6978 }
6979 struct stream_in *in = (struct stream_in *)stream;
6980 int ret = -ENOSYS;
6981
6982 lock_input_stream(in);
6983 // note: ST sessions do not close the alsa pcm driver synchronously
6984 // on standby. Therefore, we may return an error even though the
6985 // pcm stream is still opened.
6986 if (in->standby) {
6987 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6988 "%s stream in standby but pcm not NULL for non ST session", __func__);
6989 goto exit;
6990 }
6991 if (in->pcm) {
6992 struct timespec timestamp;
6993 unsigned int avail;
6994 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6995 *frames = in->frames_read + avail;
6996 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6997 ret = 0;
6998 }
6999 }
7000exit:
7001 pthread_mutex_unlock(&in->lock);
7002 return ret;
7003}
7004
Carter Hsu2e429db2019-05-14 18:50:52 +08007005static int in_update_effect_list(bool add, effect_handle_t effect,
7006 struct listnode *head)
7007{
7008 struct listnode *node;
7009 struct in_effect_list *elist = NULL;
7010 struct in_effect_list *target = NULL;
7011 int ret = 0;
7012
7013 if (!head)
7014 return ret;
7015
7016 list_for_each(node, head) {
7017 elist = node_to_item(node, struct in_effect_list, list);
7018 if (elist->handle == effect) {
7019 target = elist;
7020 break;
7021 }
7022 }
7023
7024 if (add) {
7025 if (target) {
7026 ALOGD("effect %p already exist", effect);
7027 return ret;
7028 }
7029
7030 target = (struct in_effect_list *)
7031 calloc(1, sizeof(struct in_effect_list));
7032
7033 if (!target) {
7034 ALOGE("%s:fail to allocate memory", __func__);
7035 return -ENOMEM;
7036 }
7037
7038 target->handle = effect;
7039 list_add_tail(head, &target->list);
7040 } else {
7041 if (target) {
7042 list_remove(&target->list);
7043 free(target);
7044 }
7045 }
7046
7047 return ret;
7048}
7049
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007050static int add_remove_audio_effect(const struct audio_stream *stream,
7051 effect_handle_t effect,
7052 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007053{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007054 struct stream_in *in = (struct stream_in *)stream;
7055 int status = 0;
7056 effect_descriptor_t desc;
7057
7058 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007059 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7060
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007061 if (status != 0)
7062 return status;
7063
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007064 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007065 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007066 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007067 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7068 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007069 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007070
7071 in_update_effect_list(enable, effect, &in->aec_list);
7072 enable = !list_empty(&in->aec_list);
7073 if (enable == in->enable_aec)
7074 goto exit;
7075
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007076 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007077 ALOGD("AEC enable %d", enable);
7078
Aalique Grahame22e49102018-12-18 14:23:57 -08007079 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7080 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7081 in->dev->enable_voicerx = enable;
7082 struct audio_usecase *usecase;
7083 struct listnode *node;
7084 list_for_each(node, &in->dev->usecase_list) {
7085 usecase = node_to_item(node, struct audio_usecase, list);
7086 if (usecase->type == PCM_PLAYBACK)
7087 select_devices(in->dev, usecase->id);
7088 }
7089 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007090 if (!in->standby) {
7091 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7092 select_devices(in->dev, in->usecase);
7093 }
7094
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007095 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007096 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7097
7098 in_update_effect_list(enable, effect, &in->ns_list);
7099 enable = !list_empty(&in->ns_list);
7100 if (enable == in->enable_ns)
7101 goto exit;
7102
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007103 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007104 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007105 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007106 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7107 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007108 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7109 select_devices(in->dev, in->usecase);
7110 } else
7111 select_devices(in->dev, in->usecase);
7112 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007113 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007114exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007115 pthread_mutex_unlock(&in->dev->lock);
7116 pthread_mutex_unlock(&in->lock);
7117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007118 return 0;
7119}
7120
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007121static int in_add_audio_effect(const struct audio_stream *stream,
7122 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007123{
Eric Laurent994a6932013-07-17 11:51:42 -07007124 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007125 return add_remove_audio_effect(stream, effect, true);
7126}
7127
7128static int in_remove_audio_effect(const struct audio_stream *stream,
7129 effect_handle_t effect)
7130{
Eric Laurent994a6932013-07-17 11:51:42 -07007131 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007132 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007133}
7134
Derek Chenf939fb72018-11-13 13:34:41 -08007135streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7136 audio_io_handle_t input)
7137{
7138 struct listnode *node;
7139
7140 list_for_each(node, &dev->active_inputs_list) {
7141 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7142 streams_input_ctxt_t,
7143 list);
7144 if (in_ctxt->input->capture_handle == input) {
7145 return in_ctxt;
7146 }
7147 }
7148 return NULL;
7149}
7150
7151streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7152 audio_io_handle_t output)
7153{
7154 struct listnode *node;
7155
7156 list_for_each(node, &dev->active_outputs_list) {
7157 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7158 streams_output_ctxt_t,
7159 list);
7160 if (out_ctxt->output->handle == output) {
7161 return out_ctxt;
7162 }
7163 }
7164 return NULL;
7165}
7166
Haynes Mathew George16081042017-05-31 17:16:49 -07007167static int in_stop(const struct audio_stream_in* stream)
7168{
7169 struct stream_in *in = (struct stream_in *)stream;
7170 struct audio_device *adev = in->dev;
7171
7172 int ret = -ENOSYS;
7173 ALOGV("%s", __func__);
7174 pthread_mutex_lock(&adev->lock);
7175 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7176 in->capture_started && in->pcm != NULL) {
7177 pcm_stop(in->pcm);
7178 ret = stop_input_stream(in);
7179 in->capture_started = false;
7180 }
7181 pthread_mutex_unlock(&adev->lock);
7182 return ret;
7183}
7184
7185static int in_start(const struct audio_stream_in* stream)
7186{
7187 struct stream_in *in = (struct stream_in *)stream;
7188 struct audio_device *adev = in->dev;
7189 int ret = -ENOSYS;
7190
7191 ALOGV("%s in %p", __func__, in);
7192 pthread_mutex_lock(&adev->lock);
7193 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7194 !in->capture_started && in->pcm != NULL) {
7195 if (!in->capture_started) {
7196 ret = start_input_stream(in);
7197 if (ret == 0) {
7198 in->capture_started = true;
7199 }
7200 }
7201 }
7202 pthread_mutex_unlock(&adev->lock);
7203 return ret;
7204}
7205
Phil Burke0a86d12019-02-16 22:28:11 -08007206// Read offset for the positional timestamp from a persistent vendor property.
7207// This is to workaround apparent inaccuracies in the timing information that
7208// is used by the AAudio timing model. The inaccuracies can cause glitches.
7209static int64_t in_get_mmap_time_offset() {
7210 const int32_t kDefaultOffsetMicros = 0;
7211 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007212 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007213 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7214 return mmap_time_offset_micros * (int64_t)1000;
7215}
7216
Haynes Mathew George16081042017-05-31 17:16:49 -07007217static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7218 int32_t min_size_frames,
7219 struct audio_mmap_buffer_info *info)
7220{
7221 struct stream_in *in = (struct stream_in *)stream;
7222 struct audio_device *adev = in->dev;
7223 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007224 unsigned int offset1 = 0;
7225 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007226 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007227 uint32_t mmap_size = 0;
7228 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007229
7230 pthread_mutex_lock(&adev->lock);
7231 ALOGV("%s in %p", __func__, in);
7232
Sharad Sanglec6f32552018-05-04 16:15:38 +05307233 if (CARD_STATUS_OFFLINE == in->card_status||
7234 CARD_STATUS_OFFLINE == adev->card_status) {
7235 ALOGW("in->card_status or adev->card_status offline, try again");
7236 ret = -EIO;
7237 goto exit;
7238 }
7239
Haynes Mathew George16081042017-05-31 17:16:49 -07007240 if (info == NULL || min_size_frames == 0) {
7241 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7242 ret = -EINVAL;
7243 goto exit;
7244 }
7245 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7246 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7247 ALOGV("%s in %p", __func__, in);
7248 ret = -ENOSYS;
7249 goto exit;
7250 }
7251 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7252 if (in->pcm_device_id < 0) {
7253 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7254 __func__, in->pcm_device_id, in->usecase);
7255 ret = -EINVAL;
7256 goto exit;
7257 }
7258
7259 adjust_mmap_period_count(&in->config, min_size_frames);
7260
7261 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7262 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7263 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7264 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307265 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307266 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7267 in->card_status = CARD_STATUS_OFFLINE;
7268 adev->card_status = CARD_STATUS_OFFLINE;
7269 ret = -EIO;
7270 goto exit;
7271 }
7272
Haynes Mathew George16081042017-05-31 17:16:49 -07007273 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7274 step = "open";
7275 ret = -ENODEV;
7276 goto exit;
7277 }
7278
7279 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7280 if (ret < 0) {
7281 step = "begin";
7282 goto exit;
7283 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007284
Arun Mirpuri5d170872019-03-26 13:21:31 -07007285 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7286 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7287 info->burst_size_frames = in->config.period_size;
7288 ret = platform_get_mmap_data_fd(adev->platform,
7289 in->pcm_device_id, 1 /*capture*/,
7290 &info->shared_memory_fd,
7291 &mmap_size);
7292 if (ret < 0) {
7293 // Fall back to non exclusive mode
7294 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7295 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007296 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7297 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7298
Arun Mirpuri5d170872019-03-26 13:21:31 -07007299 if (mmap_size < buffer_size) {
7300 step = "mmap";
7301 goto exit;
7302 }
7303 // FIXME: indicate exclusive mode support by returning a negative buffer size
7304 info->buffer_size_frames *= -1;
7305 }
7306
7307 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007308
7309 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7310 if (ret < 0) {
7311 step = "commit";
7312 goto exit;
7313 }
7314
Phil Burke0a86d12019-02-16 22:28:11 -08007315 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7316
Haynes Mathew George16081042017-05-31 17:16:49 -07007317 in->standby = false;
7318 ret = 0;
7319
7320 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7321 __func__, info->shared_memory_address, info->buffer_size_frames);
7322
7323exit:
7324 if (ret != 0) {
7325 if (in->pcm == NULL) {
7326 ALOGE("%s: %s - %d", __func__, step, ret);
7327 } else {
7328 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7329 pcm_close(in->pcm);
7330 in->pcm = NULL;
7331 }
7332 }
7333 pthread_mutex_unlock(&adev->lock);
7334 return ret;
7335}
7336
7337static int in_get_mmap_position(const struct audio_stream_in *stream,
7338 struct audio_mmap_position *position)
7339{
7340 struct stream_in *in = (struct stream_in *)stream;
7341 ALOGVV("%s", __func__);
7342 if (position == NULL) {
7343 return -EINVAL;
7344 }
7345 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7346 return -ENOSYS;
7347 }
7348 if (in->pcm == NULL) {
7349 return -ENOSYS;
7350 }
7351 struct timespec ts = { 0, 0 };
7352 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7353 if (ret < 0) {
7354 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7355 return ret;
7356 }
Phil Burke0a86d12019-02-16 22:28:11 -08007357 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7358 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007359 return 0;
7360}
7361
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307362static int in_get_active_microphones(const struct audio_stream_in *stream,
7363 struct audio_microphone_characteristic_t *mic_array,
7364 size_t *mic_count) {
7365 struct stream_in *in = (struct stream_in *)stream;
7366 struct audio_device *adev = in->dev;
7367 ALOGVV("%s", __func__);
7368
7369 lock_input_stream(in);
7370 pthread_mutex_lock(&adev->lock);
7371 int ret = platform_get_active_microphones(adev->platform,
7372 audio_channel_count_from_in_mask(in->channel_mask),
7373 in->usecase, mic_array, mic_count);
7374 pthread_mutex_unlock(&adev->lock);
7375 pthread_mutex_unlock(&in->lock);
7376
7377 return ret;
7378}
7379
7380static int adev_get_microphones(const struct audio_hw_device *dev,
7381 struct audio_microphone_characteristic_t *mic_array,
7382 size_t *mic_count) {
7383 struct audio_device *adev = (struct audio_device *)dev;
7384 ALOGVV("%s", __func__);
7385
7386 pthread_mutex_lock(&adev->lock);
7387 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7388 pthread_mutex_unlock(&adev->lock);
7389
7390 return ret;
7391}
juyuchendb308c22019-01-21 11:57:17 -07007392
7393static void in_update_sink_metadata(struct audio_stream_in *stream,
7394 const struct sink_metadata *sink_metadata) {
7395
7396 if (stream == NULL
7397 || sink_metadata == NULL
7398 || sink_metadata->tracks == NULL) {
7399 return;
7400 }
7401
7402 int error = 0;
7403 struct stream_in *in = (struct stream_in *)stream;
7404 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007405 struct listnode devices;
Zhou Song62ea0282020-03-22 19:53:01 +08007406 bool is_ha_usecase = false;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007407
7408 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007409
7410 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007411 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007412
7413 lock_input_stream(in);
7414 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007415 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007416
Zhou Song62ea0282020-03-22 19:53:01 +08007417 is_ha_usecase = adev->ha_proxy_enable ?
7418 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY2 :
7419 in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY;
7420 if (is_ha_usecase && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007421 && adev->voice_tx_output != NULL) {
7422 /* Use the rx device from afe-proxy record to route voice call because
7423 there is no routing if tx device is on primary hal and rx device
7424 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007425 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007426
7427 if (!voice_is_call_state_active(adev)) {
7428 if (adev->mode == AUDIO_MODE_IN_CALL) {
7429 adev->current_call_output = adev->voice_tx_output;
7430 error = voice_start_call(adev);
7431 if (error != 0)
7432 ALOGE("%s: start voice call failed %d", __func__, error);
7433 }
7434 } else {
7435 adev->current_call_output = adev->voice_tx_output;
7436 voice_update_devices_for_all_voice_usecases(adev);
7437 }
7438 }
7439
7440 pthread_mutex_unlock(&adev->lock);
7441 pthread_mutex_unlock(&in->lock);
7442}
7443
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307444int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007445 audio_io_handle_t handle,
7446 audio_devices_t devices,
7447 audio_output_flags_t flags,
7448 struct audio_config *config,
7449 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007450 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007451{
7452 struct audio_device *adev = (struct audio_device *)dev;
7453 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307454 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007455 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007456 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307457 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007458 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7459 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7460 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7461 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007462 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007463 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7464 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007465 bool force_haptic_path =
7466 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007467 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007468
kunleizdff872d2018-08-20 14:40:33 +08007469 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007470 is_usb_dev = false;
7471 devices = AUDIO_DEVICE_OUT_SPEAKER;
7472 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7473 __func__, devices);
7474 }
7475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007476 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307477
Rahul Sharma99770982019-03-06 17:05:26 +05307478 pthread_mutex_lock(&adev->lock);
7479 if (out_get_stream(adev, handle) != NULL) {
7480 ALOGW("%s, output stream already opened", __func__);
7481 ret = -EEXIST;
7482 }
7483 pthread_mutex_unlock(&adev->lock);
7484 if (ret)
7485 return ret;
7486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007487 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7488
Mingming Yin3a941d42016-02-17 18:08:05 -08007489 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007490 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7491 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307492
7493
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007494 if (!out) {
7495 return -ENOMEM;
7496 }
7497
Haynes Mathew George204045b2015-02-25 20:32:03 -08007498 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007499 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307500 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007501 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007502 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007504 if (devices == AUDIO_DEVICE_NONE)
7505 devices = AUDIO_DEVICE_OUT_SPEAKER;
7506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007507 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007508 list_init(&out->device_list);
7509 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007510 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007511 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007512 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307513 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307514 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7515 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7516 else
7517 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007518 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007519 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007520 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307521 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307522 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307523 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007524 out->hal_output_suspend_supported = 0;
7525 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307526 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307527 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307528 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007529 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007530
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307531 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307532 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007533 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7534
Aalique Grahame22e49102018-12-18 14:23:57 -08007535 if (direct_dev &&
7536 (audio_is_linear_pcm(out->format) ||
7537 config->format == AUDIO_FORMAT_DEFAULT) &&
7538 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7539 audio_format_t req_format = config->format;
7540 audio_channel_mask_t req_channel_mask = config->channel_mask;
7541 uint32_t req_sample_rate = config->sample_rate;
7542
7543 pthread_mutex_lock(&adev->lock);
7544 if (is_hdmi) {
7545 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7546 ret = read_hdmi_sink_caps(out);
7547 if (config->sample_rate == 0)
7548 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7549 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7550 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7551 if (config->format == AUDIO_FORMAT_DEFAULT)
7552 config->format = AUDIO_FORMAT_PCM_16_BIT;
7553 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007554 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7555 &config->format,
7556 &out->supported_formats[0],
7557 MAX_SUPPORTED_FORMATS,
7558 &config->channel_mask,
7559 &out->supported_channel_masks[0],
7560 MAX_SUPPORTED_CHANNEL_MASKS,
7561 &config->sample_rate,
7562 &out->supported_sample_rates[0],
7563 MAX_SUPPORTED_SAMPLE_RATES);
7564 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007565 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007566
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007567 pthread_mutex_unlock(&adev->lock);
7568 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007569 if (ret == -ENOSYS) {
7570 /* ignore and go with default */
7571 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007572 }
7573 // For MMAP NO IRQ, allow conversions in ADSP
7574 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7575 goto error_open;
7576 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007577 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007578 goto error_open;
7579 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007580
7581 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7582 config->sample_rate = req_sample_rate;
7583 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7584 config->channel_mask = req_channel_mask;
7585 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7586 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007587 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007588
7589 out->sample_rate = config->sample_rate;
7590 out->channel_mask = config->channel_mask;
7591 out->format = config->format;
7592 if (is_hdmi) {
7593 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7594 out->config = pcm_config_hdmi_multi;
7595 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7596 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7597 out->config = pcm_config_mmap_playback;
7598 out->stream.start = out_start;
7599 out->stream.stop = out_stop;
7600 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7601 out->stream.get_mmap_position = out_get_mmap_position;
7602 } else {
7603 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7604 out->config = pcm_config_hifi;
7605 }
7606
7607 out->config.rate = out->sample_rate;
7608 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7609 if (is_hdmi) {
7610 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7611 audio_bytes_per_sample(out->format));
7612 }
7613 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007614 }
7615
Derek Chenf6318be2017-06-12 17:16:24 -04007616 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007617 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007618 /* extract car audio stream index */
7619 out->car_audio_stream =
7620 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7621 if (out->car_audio_stream < 0) {
7622 ALOGE("%s: invalid car audio stream %x",
7623 __func__, out->car_audio_stream);
7624 ret = -EINVAL;
7625 goto error_open;
7626 }
Derek Chen5f67a942020-02-24 23:08:13 -08007627 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007628 }
7629
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007630 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007631 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007632 if (!voice_extn_is_compress_voip_supported()) {
7633 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7634 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007635 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7636 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007637 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7638 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007639 out->volume_l = INVALID_OUT_VOLUME;
7640 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007641
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007642 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007643 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007644 uint32_t channel_count =
7645 audio_channel_count_from_out_mask(out->channel_mask);
7646 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7647 out->sample_rate, out->format,
7648 channel_count, false);
7649 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7650 if (frame_size != 0)
7651 out->config.period_size = buffer_size / frame_size;
7652 else
7653 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007654 }
7655 } else {
7656 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7657 voice_extn_compress_voip_is_active(out->dev)) &&
7658 (voice_extn_compress_voip_is_config_supported(config))) {
7659 ret = voice_extn_compress_voip_open_output_stream(out);
7660 if (ret != 0) {
7661 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7662 __func__, ret);
7663 goto error_open;
7664 }
Sujin Panicker19027262019-09-16 18:28:06 +05307665 } else {
7666 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7667 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007668 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007669 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007670 } else if (audio_is_linear_pcm(out->format) &&
7671 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7672 out->channel_mask = config->channel_mask;
7673 out->sample_rate = config->sample_rate;
7674 out->format = config->format;
7675 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7676 // does this change?
7677 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7678 out->config.rate = config->sample_rate;
7679 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7680 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7681 audio_bytes_per_sample(config->format));
7682 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007683 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307684 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307685 pthread_mutex_lock(&adev->lock);
7686 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7687 pthread_mutex_unlock(&adev->lock);
7688
7689 // reject offload during card offline to allow
7690 // fallback to s/w paths
7691 if (offline) {
7692 ret = -ENODEV;
7693 goto error_open;
7694 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007695
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007696 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7697 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7698 ALOGE("%s: Unsupported Offload information", __func__);
7699 ret = -EINVAL;
7700 goto error_open;
7701 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007702
Atul Khare3fa6e542017-08-09 00:56:17 +05307703 if (config->offload_info.format == 0)
7704 config->offload_info.format = config->format;
7705 if (config->offload_info.sample_rate == 0)
7706 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007707
Mingming Yin90310102013-11-13 16:57:00 -08007708 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307709 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007710 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007711 ret = -EINVAL;
7712 goto error_open;
7713 }
7714
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007715 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7716 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7717 (audio_extn_passthru_is_passthrough_stream(out)) &&
7718 !((config->sample_rate == 48000) ||
7719 (config->sample_rate == 96000) ||
7720 (config->sample_rate == 192000))) {
7721 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7722 __func__, config->sample_rate, config->offload_info.format);
7723 ret = -EINVAL;
7724 goto error_open;
7725 }
7726
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007727 out->compr_config.codec = (struct snd_codec *)
7728 calloc(1, sizeof(struct snd_codec));
7729
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007730 if (!out->compr_config.codec) {
7731 ret = -ENOMEM;
7732 goto error_open;
7733 }
7734
Dhananjay Kumarac341582017-02-23 23:42:25 +05307735 out->stream.pause = out_pause;
7736 out->stream.resume = out_resume;
7737 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307738 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307739 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007740 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307741 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007742 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307743 } else {
7744 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7745 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007746 }
vivek mehta446c3962015-09-14 10:57:35 -07007747
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307748 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7749 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007750#ifdef AUDIO_GKI_ENABLED
7751 /* out->compr_config.codec->reserved[1] is for flags */
7752 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7753#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307754 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007755#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307756 }
7757
vivek mehta446c3962015-09-14 10:57:35 -07007758 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007759 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007760 config->format == 0 && config->sample_rate == 0 &&
7761 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007762 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007763 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7764 } else {
7765 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7766 ret = -EEXIST;
7767 goto error_open;
7768 }
vivek mehta446c3962015-09-14 10:57:35 -07007769 }
7770
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007771 if (config->offload_info.channel_mask)
7772 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007773 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007774 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007775 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007776 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307777 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007778 ret = -EINVAL;
7779 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007780 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007781
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007782 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007783 out->sample_rate = config->offload_info.sample_rate;
7784
Mingming Yin3ee55c62014-08-04 14:23:35 -07007785 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007786
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307787 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307788 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307789 audio_extn_dolby_send_ddp_endp_params(adev);
7790 audio_extn_dolby_set_dmid(adev);
7791 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007792
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007793 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007794 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007795 out->compr_config.codec->bit_rate =
7796 config->offload_info.bit_rate;
7797 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307798 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007799 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307800 /* Update bit width only for non passthrough usecases.
7801 * For passthrough usecases, the output will always be opened @16 bit
7802 */
7803 if (!audio_extn_passthru_is_passthrough_stream(out))
7804 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307805
7806 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007807#ifdef AUDIO_GKI_ENABLED
7808 /* out->compr_config.codec->reserved[1] is for flags */
7809 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7810 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7811#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307812 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7813 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007814#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307815
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007816 /*TODO: Do we need to change it for passthrough */
7817 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007818
Manish Dewangana6fc5442015-08-24 20:30:31 +05307819 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7820 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307821 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307822 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307823 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7824 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307825
7826 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7827 AUDIO_FORMAT_PCM) {
7828
7829 /*Based on platform support, configure appropriate alsa format for corresponding
7830 *hal input format.
7831 */
7832 out->compr_config.codec->format = hal_format_to_alsa(
7833 config->offload_info.format);
7834
Ashish Jain83a6cc22016-06-28 14:34:17 +05307835 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307836 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307837 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307838
Dhananjay Kumarac341582017-02-23 23:42:25 +05307839 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307840 *hal input format and alsa format might differ based on platform support.
7841 */
7842 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307843 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307844
7845 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7846
Deeraj Soman93155a62019-09-30 19:00:37 +05307847 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7848 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7849 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7850 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7851 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307852
Ashish Jainf1eaa582016-05-23 20:54:24 +05307853 /* Check if alsa session is configured with the same format as HAL input format,
7854 * if not then derive correct fragment size needed to accomodate the
7855 * conversion of HAL input format to alsa format.
7856 */
7857 audio_extn_utils_update_direct_pcm_fragment_size(out);
7858
7859 /*if hal input and output fragment size is different this indicates HAL input format is
7860 *not same as the alsa format
7861 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307862 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307863 /*Allocate a buffer to convert input data to the alsa configured format.
7864 *size of convert buffer is equal to the size required to hold one fragment size
7865 *worth of pcm data, this is because flinger does not write more than fragment_size
7866 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307867 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7868 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307869 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7870 ret = -ENOMEM;
7871 goto error_open;
7872 }
7873 }
7874 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7875 out->compr_config.fragment_size =
7876 audio_extn_passthru_get_buffer_size(&config->offload_info);
7877 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7878 } else {
7879 out->compr_config.fragment_size =
7880 platform_get_compress_offload_buffer_size(&config->offload_info);
7881 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7882 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007883
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307884 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7885 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7886 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007887 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307888 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007889
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307890 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7891 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7892 }
7893
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007894 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7895 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007896
Manish Dewangan69426c82017-01-30 17:35:36 +05307897 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7898 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7899 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7900 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7901 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7902 } else {
7903 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7904 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007905
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307906 memset(&out->channel_map_param, 0,
7907 sizeof(struct audio_out_channel_map_param));
7908
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007909 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307910 out->send_next_track_params = false;
7911 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007912 out->offload_state = OFFLOAD_STATE_IDLE;
7913 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007914 out->writeAt.tv_sec = 0;
7915 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007916
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007917 audio_extn_dts_create_state_notifier_node(out->usecase);
7918
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007919 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7920 __func__, config->offload_info.version,
7921 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307922
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307923 /* Check if DSD audio format is supported in codec
7924 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307925 */
7926
7927 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307928 (!platform_check_codec_dsd_support(adev->platform) ||
7929 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307930 ret = -EINVAL;
7931 goto error_open;
7932 }
7933
Ashish Jain5106d362016-05-11 19:23:33 +05307934 /* Disable gapless if any of the following is true
7935 * passthrough playback
7936 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307937 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307938 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307939 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307940 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007941 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307942 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307943 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307944 check_and_set_gapless_mode(adev, false);
7945 } else
7946 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007947
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307948 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007949 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7950 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307951 if (config->format == AUDIO_FORMAT_DSD) {
7952 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08007953#ifdef AUDIO_GKI_ENABLED
7954 /* out->compr_config.codec->reserved[0] is for compr_passthr */
7955 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
7956#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307957 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08007958#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307959 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007960
7961 create_offload_callback_thread(out);
7962
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007963 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007964 switch (config->sample_rate) {
7965 case 0:
7966 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7967 break;
7968 case 8000:
7969 case 16000:
7970 case 48000:
7971 out->sample_rate = config->sample_rate;
7972 break;
7973 default:
7974 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7975 config->sample_rate);
7976 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7977 ret = -EINVAL;
7978 goto error_open;
7979 }
7980 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7981 switch (config->channel_mask) {
7982 case AUDIO_CHANNEL_NONE:
7983 case AUDIO_CHANNEL_OUT_STEREO:
7984 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7985 break;
7986 default:
7987 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7988 config->channel_mask);
7989 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7990 ret = -EINVAL;
7991 goto error_open;
7992 }
7993 switch (config->format) {
7994 case AUDIO_FORMAT_DEFAULT:
7995 case AUDIO_FORMAT_PCM_16_BIT:
7996 out->format = AUDIO_FORMAT_PCM_16_BIT;
7997 break;
7998 default:
7999 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8000 config->format);
8001 config->format = AUDIO_FORMAT_PCM_16_BIT;
8002 ret = -EINVAL;
8003 goto error_open;
8004 }
8005
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308006 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008007 if (ret != 0) {
8008 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008009 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008010 goto error_open;
8011 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008012 } else if (is_single_device_type_equal(&out->device_list,
8013 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008014 switch (config->sample_rate) {
8015 case 0:
8016 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8017 break;
8018 case 8000:
8019 case 16000:
8020 case 48000:
8021 out->sample_rate = config->sample_rate;
8022 break;
8023 default:
8024 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8025 config->sample_rate);
8026 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8027 ret = -EINVAL;
8028 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008029 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008030 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8031 switch (config->channel_mask) {
8032 case AUDIO_CHANNEL_NONE:
8033 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8034 break;
8035 case AUDIO_CHANNEL_OUT_STEREO:
8036 out->channel_mask = config->channel_mask;
8037 break;
8038 default:
8039 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8040 config->channel_mask);
8041 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8042 ret = -EINVAL;
8043 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008044 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008045 switch (config->format) {
8046 case AUDIO_FORMAT_DEFAULT:
8047 out->format = AUDIO_FORMAT_PCM_16_BIT;
8048 break;
8049 case AUDIO_FORMAT_PCM_16_BIT:
8050 out->format = config->format;
8051 break;
8052 default:
8053 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8054 config->format);
8055 config->format = AUDIO_FORMAT_PCM_16_BIT;
8056 ret = -EINVAL;
8057 break;
8058 }
8059 if (ret != 0)
8060 goto error_open;
8061
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008062 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8063 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008064 out->config.rate = out->sample_rate;
8065 out->config.channels =
8066 audio_channel_count_from_out_mask(out->channel_mask);
8067 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008068 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008069 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308070 unsigned int channels = 0;
8071 /*Update config params to default if not set by the caller*/
8072 if (config->sample_rate == 0)
8073 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8074 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8075 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8076 if (config->format == AUDIO_FORMAT_DEFAULT)
8077 config->format = AUDIO_FORMAT_PCM_16_BIT;
8078
8079 channels = audio_channel_count_from_out_mask(out->channel_mask);
8080
Varun Balaraje49253e2017-07-06 19:48:56 +05308081 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8082 out->usecase = get_interactive_usecase(adev);
8083 out->config = pcm_config_low_latency;
8084 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308085 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008086 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8087 out->flags);
8088 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008089 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8090 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8091 out->config = pcm_config_mmap_playback;
8092 out->stream.start = out_start;
8093 out->stream.stop = out_stop;
8094 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8095 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308096 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8097 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008098 out->hal_output_suspend_supported =
8099 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8100 out->dynamic_pm_qos_config_supported =
8101 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8102 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008103 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8104 } else {
8105 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8106 //the mixer path will be a string similar to "low-latency-playback resume"
8107 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8108 strlcat(out->pm_qos_mixer_path,
8109 " resume", MAX_MIXER_PATH_LEN);
8110 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8111 out->pm_qos_mixer_path);
8112 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308113 out->config = pcm_config_low_latency;
8114 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8115 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8116 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308117 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8118 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8119 if (out->config.period_size <= 0) {
8120 ALOGE("Invalid configuration period size is not valid");
8121 ret = -EINVAL;
8122 goto error_open;
8123 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008124 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8125 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8126 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008127 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8128 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8129 out->config = pcm_config_haptics_audio;
8130 if (force_haptic_path)
8131 adev->haptics_config = pcm_config_haptics_audio;
8132 else
8133 adev->haptics_config = pcm_config_haptics;
8134
8135 out->config.channels =
8136 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8137
8138 if (force_haptic_path) {
8139 out->config.channels = 1;
8140 adev->haptics_config.channels = 1;
8141 } else
8142 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 -08008143 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008144 ret = audio_extn_auto_hal_open_output_stream(out);
8145 if (ret) {
8146 ALOGE("%s: Failed to open output stream for bus device", __func__);
8147 ret = -EINVAL;
8148 goto error_open;
8149 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308150 } else {
8151 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008152 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8153 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308154 }
8155 out->hal_ip_format = format = out->format;
8156 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8157 out->hal_op_format = pcm_format_to_hal(out->config.format);
8158 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8159 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008160 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308161 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308162 if (out->hal_ip_format != out->hal_op_format) {
8163 uint32_t buffer_size = out->config.period_size *
8164 format_to_bitwidth_table[out->hal_op_format] *
8165 out->config.channels;
8166 out->convert_buffer = calloc(1, buffer_size);
8167 if (out->convert_buffer == NULL){
8168 ALOGE("Allocation failed for convert buffer for size %d",
8169 out->compr_config.fragment_size);
8170 ret = -ENOMEM;
8171 goto error_open;
8172 }
8173 ALOGD("Convert buffer allocated of size %d", buffer_size);
8174 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008175 }
8176
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008177 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8178 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308179
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008180 /* TODO remove this hardcoding and check why width is zero*/
8181 if (out->bit_width == 0)
8182 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308183 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008184 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008185 &out->device_list, out->flags,
8186 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308187 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308188 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008189 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008190 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8191 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008192 if(adev->primary_output == NULL)
8193 adev->primary_output = out;
8194 else {
8195 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008196 ret = -EEXIST;
8197 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008198 }
8199 }
8200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008201 /* Check if this usecase is already existing */
8202 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008203 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8204 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008205 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008206 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008207 ret = -EEXIST;
8208 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008209 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008211 pthread_mutex_unlock(&adev->lock);
8212
8213 out->stream.common.get_sample_rate = out_get_sample_rate;
8214 out->stream.common.set_sample_rate = out_set_sample_rate;
8215 out->stream.common.get_buffer_size = out_get_buffer_size;
8216 out->stream.common.get_channels = out_get_channels;
8217 out->stream.common.get_format = out_get_format;
8218 out->stream.common.set_format = out_set_format;
8219 out->stream.common.standby = out_standby;
8220 out->stream.common.dump = out_dump;
8221 out->stream.common.set_parameters = out_set_parameters;
8222 out->stream.common.get_parameters = out_get_parameters;
8223 out->stream.common.add_audio_effect = out_add_audio_effect;
8224 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8225 out->stream.get_latency = out_get_latency;
8226 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008227#ifdef NO_AUDIO_OUT
8228 out->stream.write = out_write_for_no_output;
8229#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008230 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008231#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008232 out->stream.get_render_position = out_get_render_position;
8233 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008234 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008235
Haynes Mathew George16081042017-05-31 17:16:49 -07008236 if (out->realtime)
8237 out->af_period_multiplier = af_period_multiplier;
8238 else
8239 out->af_period_multiplier = 1;
8240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008241 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008242 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008243 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008244
8245 config->format = out->stream.common.get_format(&out->stream.common);
8246 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8247 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308248 register_format(out->format, out->supported_formats);
8249 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8250 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008251
Aalique Grahame22e49102018-12-18 14:23:57 -08008252 out->error_log = error_log_create(
8253 ERROR_LOG_ENTRIES,
8254 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8255
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308256 /*
8257 By locking output stream before registering, we allow the callback
8258 to update stream's state only after stream's initial state is set to
8259 adev state.
8260 */
8261 lock_output_stream(out);
8262 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8263 pthread_mutex_lock(&adev->lock);
8264 out->card_status = adev->card_status;
8265 pthread_mutex_unlock(&adev->lock);
8266 pthread_mutex_unlock(&out->lock);
8267
Aalique Grahame22e49102018-12-18 14:23:57 -08008268 stream_app_type_cfg_init(&out->app_type_cfg);
8269
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008270 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308271 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008272 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008273
8274 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8275 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8276 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008277 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308278 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008279 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008280 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308281 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8282 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008283 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8284 out->usecase, PCM_PLAYBACK);
8285 hdlr_stream_cfg.flags = out->flags;
8286 hdlr_stream_cfg.type = PCM_PLAYBACK;
8287 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8288 &hdlr_stream_cfg);
8289 if (ret) {
8290 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8291 out->adsp_hdlr_stream_handle = NULL;
8292 }
8293 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308294 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8295 is_direct_passthough, false);
8296 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8297 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008298 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008299 if (ret < 0) {
8300 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8301 out->ip_hdlr_handle = NULL;
8302 }
8303 }
Derek Chenf939fb72018-11-13 13:34:41 -08008304
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008305 ret = io_streams_map_insert(adev, &out->stream.common,
8306 out->handle, AUDIO_PATCH_HANDLE_NONE);
8307 if (ret != 0)
8308 goto error_open;
8309
Derek Chenf939fb72018-11-13 13:34:41 -08008310 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8311 calloc(1, sizeof(streams_output_ctxt_t));
8312 if (out_ctxt == NULL) {
8313 ALOGE("%s fail to allocate output ctxt", __func__);
8314 ret = -ENOMEM;
8315 goto error_open;
8316 }
8317 out_ctxt->output = out;
8318
8319 pthread_mutex_lock(&adev->lock);
8320 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8321 pthread_mutex_unlock(&adev->lock);
8322
Eric Laurent994a6932013-07-17 11:51:42 -07008323 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008324 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008325
8326error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308327 if (out->convert_buffer)
8328 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008329 free(out);
8330 *stream_out = NULL;
8331 ALOGD("%s: exit: ret %d", __func__, ret);
8332 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008333}
8334
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308335void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008336 struct audio_stream_out *stream)
8337{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008338 struct stream_out *out = (struct stream_out *)stream;
8339 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008340 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008341
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008342 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308343
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008344 io_streams_map_remove(adev, out->handle);
8345
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308346 // must deregister from sndmonitor first to prevent races
8347 // between the callback and close_stream
8348 audio_extn_snd_mon_unregister_listener(out);
8349
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008350 /* close adsp hdrl session before standby */
8351 if (out->adsp_hdlr_stream_handle) {
8352 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8353 if (ret)
8354 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8355 out->adsp_hdlr_stream_handle = NULL;
8356 }
8357
Manish Dewangan21a850a2017-08-14 12:03:55 +05308358 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008359 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8360 out->ip_hdlr_handle = NULL;
8361 }
8362
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008363 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308364 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008365 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308366 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308367 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008368 if(ret != 0)
8369 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8370 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008371 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008372 out_standby(&stream->common);
8373
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008374 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008375 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008376 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008377 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008378 if (out->compr_config.codec != NULL)
8379 free(out->compr_config.codec);
8380 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008381
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308382 out->a2dp_compress_mute = false;
8383
Varun Balaraje49253e2017-07-06 19:48:56 +05308384 if (is_interactive_usecase(out->usecase))
8385 free_interactive_usecase(adev, out->usecase);
8386
Ashish Jain83a6cc22016-06-28 14:34:17 +05308387 if (out->convert_buffer != NULL) {
8388 free(out->convert_buffer);
8389 out->convert_buffer = NULL;
8390 }
8391
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008392 if (adev->voice_tx_output == out)
8393 adev->voice_tx_output = NULL;
8394
Aalique Grahame22e49102018-12-18 14:23:57 -08008395 error_log_destroy(out->error_log);
8396 out->error_log = NULL;
8397
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308398 if (adev->primary_output == out)
8399 adev->primary_output = NULL;
8400
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008401 pthread_cond_destroy(&out->cond);
8402 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008403
8404 pthread_mutex_lock(&adev->lock);
8405 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8406 if (out_ctxt != NULL) {
8407 list_remove(&out_ctxt->list);
8408 free(out_ctxt);
8409 } else {
8410 ALOGW("%s, output stream already closed", __func__);
8411 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008412 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008413 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008414 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008415}
8416
8417static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8418{
8419 struct audio_device *adev = (struct audio_device *)dev;
8420 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008421 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008422 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008423 int ret;
8424 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008425 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008426 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008427 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008428
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008429 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008430 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008431
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308432 if (!parms)
8433 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308434
Derek Chen6f293672019-04-01 01:40:24 -07008435 /* notify adev and input/output streams on the snd card status */
8436 adev_snd_mon_cb((void *)adev, parms);
8437
8438 list_for_each(node, &adev->active_outputs_list) {
8439 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8440 streams_output_ctxt_t,
8441 list);
8442 out_snd_mon_cb((void *)out_ctxt->output, parms);
8443 }
8444
8445 list_for_each(node, &adev->active_inputs_list) {
8446 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8447 streams_input_ctxt_t,
8448 list);
8449 in_snd_mon_cb((void *)in_ctxt->input, parms);
8450 }
8451
Zhou Songd6d71752019-05-21 18:08:51 +08008452 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308453 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8454 if (ret >= 0) {
8455 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008456 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308457 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008458 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308459 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008460 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008461 }
8462 }
8463
8464 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8465 if (ret>=0) {
8466 if (!strncmp(value, "false", 5) &&
8467 audio_extn_a2dp_source_is_suspended()) {
8468 struct audio_usecase *usecase;
8469 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008470 list_for_each(node, &adev->usecase_list) {
8471 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008472 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008473 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008474 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008475 reassign_device_list(&usecase->stream.in->device_list,
8476 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008477 select_devices(adev, usecase->id);
8478 }
Zhou Songd6d71752019-05-21 18:08:51 +08008479 }
8480 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308481 }
8482
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008483 status = voice_set_parameters(adev, parms);
8484 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008485 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008486
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008487 status = platform_set_parameters(adev->platform, parms);
8488 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008489 goto done;
8490
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008491 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8492 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008493 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008494 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8495 adev->bluetooth_nrec = true;
8496 else
8497 adev->bluetooth_nrec = false;
8498 }
8499
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008500 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8501 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008502 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8503 adev->screen_off = false;
8504 else
8505 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008506 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008507 }
8508
Eric Laurent4b084132018-10-19 17:33:43 -07008509 ret = str_parms_get_int(parms, "rotation", &val);
8510 if (ret >= 0) {
8511 bool reverse_speakers = false;
8512 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8513 switch (val) {
8514 // FIXME: note that the code below assumes that the speakers are in the correct placement
8515 // relative to the user when the device is rotated 90deg from its default rotation. This
8516 // assumption is device-specific, not platform-specific like this code.
8517 case 270:
8518 reverse_speakers = true;
8519 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8520 break;
8521 case 0:
8522 case 180:
8523 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8524 break;
8525 case 90:
8526 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8527 break;
8528 default:
8529 ALOGE("%s: unexpected rotation of %d", __func__, val);
8530 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008531 }
Eric Laurent4b084132018-10-19 17:33:43 -07008532 if (status == 0) {
8533 // check and set swap
8534 // - check if orientation changed and speaker active
8535 // - set rotation and cache the rotation value
8536 adev->camera_orientation =
8537 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8538 if (!audio_extn_is_maxx_audio_enabled())
8539 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8540 }
8541 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008542
Mingming Yin514a8bc2014-07-29 15:22:21 -07008543 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8544 if (ret >= 0) {
8545 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8546 adev->bt_wb_speech_enabled = true;
8547 else
8548 adev->bt_wb_speech_enabled = false;
8549 }
8550
Zhou Song12c29502019-03-16 10:37:18 +08008551 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8552 if (ret >= 0) {
8553 val = atoi(value);
8554 adev->swb_speech_mode = val;
8555 }
8556
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008557 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8558 if (ret >= 0) {
8559 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308560 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008561 if (audio_is_output_device(val) &&
8562 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008563 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008564 platform_get_controller_stream_from_params(parms, &controller, &stream);
8565 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8566 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008567 if (ret < 0) {
8568 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308569 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008570 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008571 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308572 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008573 /*
8574 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8575 * Per AudioPolicyManager, USB device is higher priority than WFD.
8576 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8577 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8578 * starting voice call on USB
8579 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008580 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308581 if (ret >= 0)
8582 audio_extn_usb_add_device(device, atoi(value));
8583
Zhou Song6f862822017-11-06 17:27:57 +08008584 if (!audio_extn_usb_is_tunnel_supported()) {
8585 ALOGV("detected USB connect .. disable proxy");
8586 adev->allow_afe_proxy_usage = false;
8587 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008588 }
8589 }
8590
8591 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8592 if (ret >= 0) {
8593 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308594 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008595 /*
8596 * The HDMI / Displayport disconnect handling has been moved to
8597 * audio extension to ensure that its parameters are not
8598 * invalidated prior to updating sysfs of the disconnect event
8599 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8600 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308601 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008602 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308603 if (ret >= 0)
8604 audio_extn_usb_remove_device(device, atoi(value));
8605
Zhou Song6f862822017-11-06 17:27:57 +08008606 if (!audio_extn_usb_is_tunnel_supported()) {
8607 ALOGV("detected USB disconnect .. enable proxy");
8608 adev->allow_afe_proxy_usage = true;
8609 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008610 }
8611 }
8612
Aalique Grahame22e49102018-12-18 14:23:57 -08008613 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008614 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008615
8616 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008617 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308618 struct audio_usecase *usecase;
8619 struct listnode *node;
8620 list_for_each(node, &adev->usecase_list) {
8621 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308622 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008623 is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308624 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008625 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308626 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008627 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308628 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308629 ALOGD("Switching to speaker and muting the stream before select_devices");
8630 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308631 //force device switch to re configure encoder
8632 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308633 ALOGD("Unmuting the stream after select_devices");
8634 usecase->stream.out->a2dp_compress_mute = false;
8635 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 +05308636 audio_extn_a2dp_set_handoff_mode(false);
8637 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308638 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308639 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8640 usecase->stream.out->a2dp_compress_mute) {
8641 pthread_mutex_unlock(&adev->lock);
8642 lock_output_stream(usecase->stream.out);
8643 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008644 reassign_device_list(&usecase->stream.out->device_list,
8645 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308646 check_a2dp_restore_l(adev, usecase->stream.out, true);
8647 pthread_mutex_unlock(&usecase->stream.out->lock);
8648 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308649 }
8650 }
8651 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008652
8653 //handle vr audio setparam
8654 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8655 value, sizeof(value));
8656 if (ret >= 0) {
8657 ALOGI("Setting vr mode to be %s", value);
8658 if (!strncmp(value, "true", 4)) {
8659 adev->vr_audio_mode_enabled = true;
8660 ALOGI("Setting vr mode to true");
8661 } else if (!strncmp(value, "false", 5)) {
8662 adev->vr_audio_mode_enabled = false;
8663 ALOGI("Setting vr mode to false");
8664 } else {
8665 ALOGI("wrong vr mode set");
8666 }
8667 }
8668
Eric Laurent4b084132018-10-19 17:33:43 -07008669 //FIXME: to be replaced by proper video capture properties API
8670 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8671 if (ret >= 0) {
8672 int camera_facing = CAMERA_FACING_BACK;
8673 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8674 camera_facing = CAMERA_FACING_FRONT;
8675 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8676 camera_facing = CAMERA_FACING_BACK;
8677 else {
8678 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8679 goto done;
8680 }
8681 adev->camera_orientation =
8682 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8683 struct audio_usecase *usecase;
8684 struct listnode *node;
8685 list_for_each(node, &adev->usecase_list) {
8686 usecase = node_to_item(node, struct audio_usecase, list);
8687 struct stream_in *in = usecase->stream.in;
8688 if (usecase->type == PCM_CAPTURE && in != NULL &&
8689 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8690 select_devices(adev, in->usecase);
8691 }
8692 }
8693 }
8694
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308695 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008696done:
8697 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008698 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308699error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008700 ALOGV("%s: exit with code(%d)", __func__, status);
8701 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008702}
8703
8704static char* adev_get_parameters(const struct audio_hw_device *dev,
8705 const char *keys)
8706{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308707 ALOGD("%s:%s", __func__, keys);
8708
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008709 struct audio_device *adev = (struct audio_device *)dev;
8710 struct str_parms *reply = str_parms_create();
8711 struct str_parms *query = str_parms_create_str(keys);
8712 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308713 char value[256] = {0};
8714 int ret = 0;
8715
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008716 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008717 if (reply) {
8718 str_parms_destroy(reply);
8719 }
8720 if (query) {
8721 str_parms_destroy(query);
8722 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008723 ALOGE("adev_get_parameters: failed to create query or reply");
8724 return NULL;
8725 }
8726
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008727 //handle vr audio getparam
8728
8729 ret = str_parms_get_str(query,
8730 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8731 value, sizeof(value));
8732
8733 if (ret >= 0) {
8734 bool vr_audio_enabled = false;
8735 pthread_mutex_lock(&adev->lock);
8736 vr_audio_enabled = adev->vr_audio_mode_enabled;
8737 pthread_mutex_unlock(&adev->lock);
8738
8739 ALOGI("getting vr mode to %d", vr_audio_enabled);
8740
8741 if (vr_audio_enabled) {
8742 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8743 "true");
8744 goto exit;
8745 } else {
8746 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8747 "false");
8748 goto exit;
8749 }
8750 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008751
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008752 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008753 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008754 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008755 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008756 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308757 pthread_mutex_unlock(&adev->lock);
8758
Naresh Tannirud7205b62014-06-20 02:54:48 +05308759exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008760 str = str_parms_to_str(reply);
8761 str_parms_destroy(query);
8762 str_parms_destroy(reply);
8763
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308764 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008765 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008766}
8767
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008768static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008769{
8770 return 0;
8771}
8772
8773static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8774{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008775 int ret;
8776 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008777
8778 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8779
Haynes Mathew George5191a852013-09-11 14:19:36 -07008780 pthread_mutex_lock(&adev->lock);
8781 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008782 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008783 pthread_mutex_unlock(&adev->lock);
8784 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008785}
8786
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008787static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8788 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008789{
8790 return -ENOSYS;
8791}
8792
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008793static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8794 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008795{
8796 return -ENOSYS;
8797}
8798
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008799static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8800 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008801{
8802 return -ENOSYS;
8803}
8804
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008805static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8806 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008807{
8808 return -ENOSYS;
8809}
8810
8811static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8812{
8813 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008814 struct listnode *node;
8815 struct audio_usecase *usecase = NULL;
8816 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008818 pthread_mutex_lock(&adev->lock);
8819 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008820 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008821 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008822 if (voice_is_in_call(adev) &&
8823 (mode == AUDIO_MODE_NORMAL ||
8824 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008825 list_for_each(node, &adev->usecase_list) {
8826 usecase = node_to_item(node, struct audio_usecase, list);
8827 if (usecase->type == VOICE_CALL)
8828 break;
8829 }
8830 if (usecase &&
8831 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8832 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8833 true);
8834 if (ret != 0) {
8835 /* default service interval was successfully updated,
8836 reopen USB backend with new service interval */
8837 check_usecases_codec_backend(adev,
8838 usecase,
8839 usecase->out_snd_device);
8840 }
8841 }
8842
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008843 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008844 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008845 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008846 // restore device for other active usecases after stop call
8847 list_for_each(node, &adev->usecase_list) {
8848 usecase = node_to_item(node, struct audio_usecase, list);
8849 select_devices(adev, usecase->id);
8850 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008851 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008852 }
8853 pthread_mutex_unlock(&adev->lock);
8854 return 0;
8855}
8856
8857static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8858{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008859 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008860 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008861
8862 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008863 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008864 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008865
Derek Chend2530072014-11-24 12:39:14 -08008866 if (adev->ext_hw_plugin)
8867 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008868
8869 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008870 pthread_mutex_unlock(&adev->lock);
8871
8872 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008873}
8874
8875static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8876{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008877 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008878 return 0;
8879}
8880
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008881static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008882 const struct audio_config *config)
8883{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008884 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008885
Aalique Grahame22e49102018-12-18 14:23:57 -08008886 /* Don't know if USB HIFI in this context so use true to be conservative */
8887 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8888 true /*is_usb_hifi */) != 0)
8889 return 0;
8890
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008891 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8892 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008893}
8894
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008895static bool adev_input_allow_hifi_record(struct audio_device *adev,
8896 audio_devices_t devices,
8897 audio_input_flags_t flags,
8898 audio_source_t source) {
8899 const bool allowed = true;
8900
8901 if (!audio_is_usb_in_device(devices))
8902 return !allowed;
8903
8904 switch (flags) {
8905 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008906 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008907 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8908 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008909 default:
8910 return !allowed;
8911 }
8912
8913 switch (source) {
8914 case AUDIO_SOURCE_DEFAULT:
8915 case AUDIO_SOURCE_MIC:
8916 case AUDIO_SOURCE_UNPROCESSED:
8917 break;
8918 default:
8919 return !allowed;
8920 }
8921
8922 switch (adev->mode) {
8923 case 0:
8924 break;
8925 default:
8926 return !allowed;
8927 }
8928
8929 return allowed;
8930}
8931
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008932static int adev_update_voice_comm_input_stream(struct stream_in *in,
8933 struct audio_config *config)
8934{
8935 bool valid_rate = (config->sample_rate == 8000 ||
8936 config->sample_rate == 16000 ||
8937 config->sample_rate == 32000 ||
8938 config->sample_rate == 48000);
8939 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8940
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008941 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008942 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008943 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8944 in->config = default_pcm_config_voip_copp;
8945 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8946 DEFAULT_VOIP_BUF_DURATION_MS,
8947 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008948 } else {
8949 ALOGW("%s No valid input in voip, use defaults"
8950 "sample rate %u, channel mask 0x%X",
8951 __func__, config->sample_rate, in->channel_mask);
8952 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008953 in->config.rate = config->sample_rate;
8954 in->sample_rate = config->sample_rate;
8955 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008956 //XXX needed for voice_extn_compress_voip_open_input_stream
8957 in->config.rate = config->sample_rate;
8958 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05308959 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008960 voice_extn_compress_voip_is_active(in->dev)) &&
8961 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8962 valid_rate && valid_ch) {
8963 voice_extn_compress_voip_open_input_stream(in);
8964 // update rate entries to match config from AF
8965 in->config.rate = config->sample_rate;
8966 in->sample_rate = config->sample_rate;
8967 } else {
8968 ALOGW("%s compress voip not active, use defaults", __func__);
8969 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008970 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008971 return 0;
8972}
8973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008974static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008975 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008976 audio_devices_t devices,
8977 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008978 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308979 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008980 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008981 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008982{
8983 struct audio_device *adev = (struct audio_device *)dev;
8984 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008985 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008986 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008987 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308988 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008989 bool is_usb_dev = audio_is_usb_in_device(devices);
8990 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8991 devices,
8992 flags,
8993 source);
Andy Hung94320602018-10-29 18:31:12 -07008994 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8995 " sample_rate %u, channel_mask %#x, format %#x",
8996 __func__, flags, is_usb_dev, may_use_hifi_record,
8997 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308998
kunleizdff872d2018-08-20 14:40:33 +08008999 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009000 is_usb_dev = false;
9001 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9002 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9003 __func__, devices);
9004 }
9005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009006 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009007
9008 if (!(is_usb_dev && may_use_hifi_record)) {
9009 if (config->sample_rate == 0)
9010 config->sample_rate = 48000;
9011 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9012 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9013 if (config->format == AUDIO_FORMAT_DEFAULT)
9014 config->format = AUDIO_FORMAT_PCM_16_BIT;
9015
9016 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9017
Aalique Grahame22e49102018-12-18 14:23:57 -08009018 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9019 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009020 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309021 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009022
Rahul Sharma99770982019-03-06 17:05:26 +05309023 pthread_mutex_lock(&adev->lock);
9024 if (in_get_stream(adev, handle) != NULL) {
9025 ALOGW("%s, input stream already opened", __func__);
9026 ret = -EEXIST;
9027 }
9028 pthread_mutex_unlock(&adev->lock);
9029 if (ret)
9030 return ret;
9031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009032 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009033
9034 if (!in) {
9035 ALOGE("failed to allocate input stream");
9036 return -ENOMEM;
9037 }
9038
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309039 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309040 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9041 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009042 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009043 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009045 in->stream.common.get_sample_rate = in_get_sample_rate;
9046 in->stream.common.set_sample_rate = in_set_sample_rate;
9047 in->stream.common.get_buffer_size = in_get_buffer_size;
9048 in->stream.common.get_channels = in_get_channels;
9049 in->stream.common.get_format = in_get_format;
9050 in->stream.common.set_format = in_set_format;
9051 in->stream.common.standby = in_standby;
9052 in->stream.common.dump = in_dump;
9053 in->stream.common.set_parameters = in_set_parameters;
9054 in->stream.common.get_parameters = in_get_parameters;
9055 in->stream.common.add_audio_effect = in_add_audio_effect;
9056 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9057 in->stream.set_gain = in_set_gain;
9058 in->stream.read = in_read;
9059 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009060 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309061 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009062 in->stream.set_microphone_direction = in_set_microphone_direction;
9063 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009064 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009065
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009066 list_init(&in->device_list);
9067 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009068 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009069 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009070 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009071 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009072 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009073 in->bit_width = 16;
9074 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009075 in->direction = MIC_DIRECTION_UNSPECIFIED;
9076 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009077 list_init(&in->aec_list);
9078 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009079 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009080
Andy Hung94320602018-10-29 18:31:12 -07009081 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009082 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9083 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9084 /* Force channel config requested to mono if incall
9085 record is being requested for only uplink/downlink */
9086 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9087 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9088 ret = -EINVAL;
9089 goto err_open;
9090 }
9091 }
9092
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009093 if (is_usb_dev && may_use_hifi_record) {
9094 /* HiFi record selects an appropriate format, channel, rate combo
9095 depending on sink capabilities*/
9096 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9097 &config->format,
9098 &in->supported_formats[0],
9099 MAX_SUPPORTED_FORMATS,
9100 &config->channel_mask,
9101 &in->supported_channel_masks[0],
9102 MAX_SUPPORTED_CHANNEL_MASKS,
9103 &config->sample_rate,
9104 &in->supported_sample_rates[0],
9105 MAX_SUPPORTED_SAMPLE_RATES);
9106 if (ret != 0) {
9107 ret = -EINVAL;
9108 goto err_open;
9109 }
9110 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009111 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309112 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309113 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9114 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9115 in->config.format = PCM_FORMAT_S32_LE;
9116 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309117 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9118 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9119 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9120 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9121 bool ret_error = false;
9122 in->bit_width = 24;
9123 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9124 from HAL is 24_packed and 8_24
9125 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9126 24_packed return error indicating supported format is 24_packed
9127 *> In case of any other source requesting 24 bit or float return error
9128 indicating format supported is 16 bit only.
9129
9130 on error flinger will retry with supported format passed
9131 */
9132 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9133 (source != AUDIO_SOURCE_CAMCORDER)) {
9134 config->format = AUDIO_FORMAT_PCM_16_BIT;
9135 if (config->sample_rate > 48000)
9136 config->sample_rate = 48000;
9137 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009138 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9139 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309140 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9141 ret_error = true;
9142 }
9143
9144 if (ret_error) {
9145 ret = -EINVAL;
9146 goto err_open;
9147 }
9148 }
9149
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009150 in->channel_mask = config->channel_mask;
9151 in->format = config->format;
9152
9153 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309154
9155 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9156 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9157 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9158 else {
9159 ret = -EINVAL;
9160 goto err_open;
9161 }
9162 }
9163
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009164 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309165 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9166 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009167 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9168 is_low_latency = true;
9169#if LOW_LATENCY_CAPTURE_USE_CASE
9170 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9171#endif
9172 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009173 if (!in->realtime) {
9174 in->config = pcm_config_audio_capture;
9175 frame_size = audio_stream_in_frame_size(&in->stream);
9176 buffer_size = get_input_buffer_size(config->sample_rate,
9177 config->format,
9178 channel_count,
9179 is_low_latency);
9180 in->config.period_size = buffer_size / frame_size;
9181 in->config.rate = config->sample_rate;
9182 in->af_period_multiplier = 1;
9183 } else {
9184 // period size is left untouched for rt mode playback
9185 in->config = pcm_config_audio_capture_rt;
9186 in->af_period_multiplier = af_period_multiplier;
9187 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009188 }
9189
9190 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9191 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9192 in->realtime = 0;
9193 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9194 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009195 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009196 in->stream.start = in_start;
9197 in->stream.stop = in_stop;
9198 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9199 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009200 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
9201 } else if (in->realtime) {
9202 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07009203 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009204 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009205 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009206 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9207 in->config = pcm_config_audio_capture;
9208 frame_size = audio_stream_in_frame_size(&in->stream);
9209 buffer_size = get_input_buffer_size(config->sample_rate,
9210 config->format,
9211 channel_count,
9212 false /*is_low_latency*/);
9213 in->config.period_size = buffer_size / frame_size;
9214 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009215 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009216 switch (config->format) {
9217 case AUDIO_FORMAT_PCM_32_BIT:
9218 in->bit_width = 32;
9219 break;
9220 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9221 case AUDIO_FORMAT_PCM_8_24_BIT:
9222 in->bit_width = 24;
9223 break;
9224 default:
9225 in->bit_width = 16;
9226 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009227 } else if (is_single_device_type_equal(&in->device_list,
9228 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9229 is_single_device_type_equal(&in->device_list,
9230 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009231 if (config->sample_rate == 0)
9232 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9233 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9234 config->sample_rate != 8000) {
9235 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9236 ret = -EINVAL;
9237 goto err_open;
9238 }
9239 if (config->format == AUDIO_FORMAT_DEFAULT)
9240 config->format = AUDIO_FORMAT_PCM_16_BIT;
9241 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9242 config->format = AUDIO_FORMAT_PCM_16_BIT;
9243 ret = -EINVAL;
9244 goto err_open;
9245 }
9246
9247 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
Zhou Song62ea0282020-03-22 19:53:01 +08009248 if (adev->ha_proxy_enable &&
9249 is_single_device_type_equal(&in->device_list,
9250 AUDIO_DEVICE_IN_TELEPHONY_RX))
9251 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY2;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009252 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009253 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009254 in->af_period_multiplier = 1;
9255 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9256 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9257 (config->sample_rate == 8000 ||
9258 config->sample_rate == 16000 ||
9259 config->sample_rate == 32000 ||
9260 config->sample_rate == 48000) &&
9261 channel_count == 1) {
9262 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9263 in->config = pcm_config_audio_capture;
9264 frame_size = audio_stream_in_frame_size(&in->stream);
9265 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9266 config->sample_rate,
9267 config->format,
9268 channel_count, false /*is_low_latency*/);
9269 in->config.period_size = buffer_size / frame_size;
9270 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9271 in->config.rate = config->sample_rate;
9272 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009273 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309274 int ret_val;
9275 pthread_mutex_lock(&adev->lock);
9276 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9277 in, config, &channel_mask_updated);
9278 pthread_mutex_unlock(&adev->lock);
9279
9280 if (!ret_val) {
9281 if (channel_mask_updated == true) {
9282 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9283 __func__, config->channel_mask);
9284 ret = -EINVAL;
9285 goto err_open;
9286 }
9287 ALOGD("%s: created multi-channel session succesfully",__func__);
9288 } else if (audio_extn_compr_cap_enabled() &&
9289 audio_extn_compr_cap_format_supported(config->format) &&
9290 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9291 audio_extn_compr_cap_init(in);
9292 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309293 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309294 if (ret)
9295 goto err_open;
9296 } else {
9297 in->config = pcm_config_audio_capture;
9298 in->config.rate = config->sample_rate;
9299 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309300 in->format = config->format;
9301 frame_size = audio_stream_in_frame_size(&in->stream);
9302 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009303 config->format,
9304 channel_count,
9305 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009306 /* prevent division-by-zero */
9307 if (frame_size == 0) {
9308 ALOGE("%s: Error frame_size==0", __func__);
9309 ret = -EINVAL;
9310 goto err_open;
9311 }
9312
Revathi Uddarajud2634032017-12-07 14:42:34 +05309313 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009314 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009315
Revathi Uddarajud2634032017-12-07 14:42:34 +05309316 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9317 /* optionally use VOIP usecase depending on config(s) */
9318 ret = adev_update_voice_comm_input_stream(in, config);
9319 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009320
Revathi Uddarajud2634032017-12-07 14:42:34 +05309321 if (ret) {
9322 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9323 goto err_open;
9324 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009325 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309326
9327 /* assign concurrent capture usecase if record has to caried out from
9328 * actual hardware input source */
9329 if (audio_extn_is_concurrent_capture_enabled() &&
9330 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309331 /* Acquire lock to avoid two concurrent use cases initialized to
9332 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009333
Samyak Jainc37062f2019-04-25 18:41:06 +05309334 if (in->usecase == USECASE_AUDIO_RECORD) {
9335 pthread_mutex_lock(&adev->lock);
9336 if (!(adev->pcm_record_uc_state)) {
9337 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9338 adev->pcm_record_uc_state = 1;
9339 pthread_mutex_unlock(&adev->lock);
9340 } else {
9341 pthread_mutex_unlock(&adev->lock);
9342 /* Assign compress record use case for second record */
9343 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9344 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9345 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9346 if (audio_extn_cin_applicable_stream(in)) {
9347 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309348 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309349 if (ret)
9350 goto err_open;
9351 }
9352 }
9353 }
kunleiz28c73e72019-03-27 17:24:04 +08009354 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009355 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309356 if (audio_extn_ssr_get_stream() != in)
9357 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009358
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009359 in->sample_rate = in->config.rate;
9360
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309361 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9362 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009363 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009364 in->sample_rate, in->bit_width,
9365 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309366 register_format(in->format, in->supported_formats);
9367 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9368 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309369
Aalique Grahame22e49102018-12-18 14:23:57 -08009370 in->error_log = error_log_create(
9371 ERROR_LOG_ENTRIES,
9372 1000000000 /* aggregate consecutive identical errors within one second */);
9373
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009374 /* This stream could be for sound trigger lab,
9375 get sound trigger pcm if present */
9376 audio_extn_sound_trigger_check_and_get_session(in);
9377
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309378 lock_input_stream(in);
9379 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9380 pthread_mutex_lock(&adev->lock);
9381 in->card_status = adev->card_status;
9382 pthread_mutex_unlock(&adev->lock);
9383 pthread_mutex_unlock(&in->lock);
9384
Aalique Grahame22e49102018-12-18 14:23:57 -08009385 stream_app_type_cfg_init(&in->app_type_cfg);
9386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009387 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009388
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009389 ret = io_streams_map_insert(adev, &in->stream.common,
9390 handle, AUDIO_PATCH_HANDLE_NONE);
9391 if (ret != 0)
9392 goto err_open;
9393
Derek Chenf939fb72018-11-13 13:34:41 -08009394 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9395 calloc(1, sizeof(streams_input_ctxt_t));
9396 if (in_ctxt == NULL) {
9397 ALOGE("%s fail to allocate input ctxt", __func__);
9398 ret = -ENOMEM;
9399 goto err_open;
9400 }
9401 in_ctxt->input = in;
9402
9403 pthread_mutex_lock(&adev->lock);
9404 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9405 pthread_mutex_unlock(&adev->lock);
9406
Eric Laurent994a6932013-07-17 11:51:42 -07009407 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009408 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009409
9410err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309411 if (in->usecase == USECASE_AUDIO_RECORD) {
9412 pthread_mutex_lock(&adev->lock);
9413 adev->pcm_record_uc_state = 0;
9414 pthread_mutex_unlock(&adev->lock);
9415 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009416 free(in);
9417 *stream_in = NULL;
9418 return ret;
9419}
9420
9421static void adev_close_input_stream(struct audio_hw_device *dev,
9422 struct audio_stream_in *stream)
9423{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009424 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009425 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009426 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309427
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309428 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009429
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009430 if (in == NULL) {
9431 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9432 return;
9433 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009434 io_streams_map_remove(adev, in->capture_handle);
9435
kunleiz70e57612018-12-28 17:50:23 +08009436 /* must deregister from sndmonitor first to prevent races
9437 * between the callback and close_stream
9438 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309439 audio_extn_snd_mon_unregister_listener(stream);
9440
kunleiz70e57612018-12-28 17:50:23 +08009441 /* Disable echo reference if there are no active input, hfp call
9442 * and sound trigger while closing input stream
9443 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009444 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009445 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009446 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9447 struct listnode out_devices;
9448 list_init(&out_devices);
9449 platform_set_echo_reference(adev, false, &out_devices);
9450 } else
kunleiz70e57612018-12-28 17:50:23 +08009451 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309452
Weiyin Jiang2995f662019-04-17 14:25:12 +08009453 error_log_destroy(in->error_log);
9454 in->error_log = NULL;
9455
Pallavid7c7a272018-01-16 11:22:55 +05309456
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009457 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309458 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009459 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309460 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009461 if (ret != 0)
9462 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9463 __func__, ret);
9464 } else
9465 in_standby(&stream->common);
9466
Revathi Uddarajud2634032017-12-07 14:42:34 +05309467 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309468 if (in->usecase == USECASE_AUDIO_RECORD) {
9469 adev->pcm_record_uc_state = 0;
9470 }
9471
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009472 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9473 adev->enable_voicerx = false;
9474 }
9475
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009476 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009477 audio_extn_ssr_deinit();
9478 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009479
Garmond Leunge2433c32017-09-28 21:51:22 -07009480 if (audio_extn_ffv_get_stream() == in) {
9481 audio_extn_ffv_stream_deinit();
9482 }
9483
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309484 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009485 audio_extn_compr_cap_format_supported(in->config.format))
9486 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309487
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309488 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05309489 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009490
Mingming Yinfd7607b2016-01-22 12:48:44 -08009491 if (in->is_st_session) {
9492 ALOGV("%s: sound trigger pcm stop lab", __func__);
9493 audio_extn_sound_trigger_stop_lab(in);
9494 }
Derek Chenf939fb72018-11-13 13:34:41 -08009495 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9496 if (in_ctxt != NULL) {
9497 list_remove(&in_ctxt->list);
9498 free(in_ctxt);
9499 } else {
9500 ALOGW("%s, input stream already closed", __func__);
9501 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009502 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309503 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009504 return;
9505}
9506
Aalique Grahame22e49102018-12-18 14:23:57 -08009507/* verifies input and output devices and their capabilities.
9508 *
9509 * This verification is required when enabling extended bit-depth or
9510 * sampling rates, as not all qcom products support it.
9511 *
9512 * Suitable for calling only on initialization such as adev_open().
9513 * It fills the audio_device use_case_table[] array.
9514 *
9515 * Has a side-effect that it needs to configure audio routing / devices
9516 * in order to power up the devices and read the device parameters.
9517 * It does not acquire any hw device lock. Should restore the devices
9518 * back to "normal state" upon completion.
9519 */
9520static int adev_verify_devices(struct audio_device *adev)
9521{
9522 /* enumeration is a bit difficult because one really wants to pull
9523 * the use_case, device id, etc from the hidden pcm_device_table[].
9524 * In this case there are the following use cases and device ids.
9525 *
9526 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9527 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9528 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9529 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9530 * [USECASE_AUDIO_RECORD] = {0, 0},
9531 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9532 * [USECASE_VOICE_CALL] = {2, 2},
9533 *
9534 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9535 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9536 */
9537
9538 /* should be the usecases enabled in adev_open_input_stream() */
9539 static const int test_in_usecases[] = {
9540 USECASE_AUDIO_RECORD,
9541 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9542 };
9543 /* should be the usecases enabled in adev_open_output_stream()*/
9544 static const int test_out_usecases[] = {
9545 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9546 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9547 };
9548 static const usecase_type_t usecase_type_by_dir[] = {
9549 PCM_PLAYBACK,
9550 PCM_CAPTURE,
9551 };
9552 static const unsigned flags_by_dir[] = {
9553 PCM_OUT,
9554 PCM_IN,
9555 };
9556
9557 size_t i;
9558 unsigned dir;
9559 const unsigned card_id = adev->snd_card;
9560
9561 for (dir = 0; dir < 2; ++dir) {
9562 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9563 const unsigned flags_dir = flags_by_dir[dir];
9564 const size_t testsize =
9565 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9566 const int *testcases =
9567 dir ? test_in_usecases : test_out_usecases;
9568 const audio_devices_t audio_device =
9569 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9570
9571 for (i = 0; i < testsize; ++i) {
9572 const audio_usecase_t audio_usecase = testcases[i];
9573 int device_id;
9574 struct pcm_params **pparams;
9575 struct stream_out out;
9576 struct stream_in in;
9577 struct audio_usecase uc_info;
9578 int retval;
9579
9580 pparams = &adev->use_case_table[audio_usecase];
9581 pcm_params_free(*pparams); /* can accept null input */
9582 *pparams = NULL;
9583
9584 /* find the device ID for the use case (signed, for error) */
9585 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9586 if (device_id < 0)
9587 continue;
9588
9589 /* prepare structures for device probing */
9590 memset(&uc_info, 0, sizeof(uc_info));
9591 uc_info.id = audio_usecase;
9592 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009593 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009594 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009595 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009596 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009597 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009598 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9599 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009600 }
9601 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009602 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009603 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009604 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009605 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009606 uc_info.in_snd_device = SND_DEVICE_NONE;
9607 uc_info.out_snd_device = SND_DEVICE_NONE;
9608 list_add_tail(&adev->usecase_list, &uc_info.list);
9609
9610 /* select device - similar to start_(in/out)put_stream() */
9611 retval = select_devices(adev, audio_usecase);
9612 if (retval >= 0) {
9613 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9614#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009615 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009616 if (*pparams) {
9617 ALOGV("%s: (%s) card %d device %d", __func__,
9618 dir ? "input" : "output", card_id, device_id);
9619 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9620 } else {
9621 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9622 }
9623#endif
9624 }
9625
9626 /* deselect device - similar to stop_(in/out)put_stream() */
9627 /* 1. Get and set stream specific mixer controls */
9628 retval = disable_audio_route(adev, &uc_info);
9629 /* 2. Disable the rx device */
9630 retval = disable_snd_device(adev,
9631 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9632 list_remove(&uc_info.list);
9633 }
9634 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009635 return 0;
9636}
9637
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009638int update_patch(unsigned int num_sources,
9639 const struct audio_port_config *sources,
9640 unsigned int num_sinks,
9641 const struct audio_port_config *sinks,
9642 audio_patch_handle_t handle,
9643 struct audio_patch_info *p_info,
9644 patch_type_t patch_type, bool new_patch)
9645{
9646 ALOGD("%s: enter", __func__);
9647
9648 if (p_info == NULL) {
9649 ALOGE("%s: Invalid patch pointer", __func__);
9650 return -EINVAL;
9651 }
9652
9653 if (new_patch) {
9654 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9655 if (p_info->patch == NULL) {
9656 ALOGE("%s: Could not allocate patch", __func__);
9657 return -ENOMEM;
9658 }
9659 }
9660
9661 p_info->patch->id = handle;
9662 p_info->patch->num_sources = num_sources;
9663 p_info->patch->num_sinks = num_sinks;
9664
9665 for (int i = 0; i < num_sources; i++)
9666 p_info->patch->sources[i] = sources[i];
9667 for (int i = 0; i < num_sinks; i++)
9668 p_info->patch->sinks[i] = sinks[i];
9669
9670 p_info->patch_type = patch_type;
9671 return 0;
9672}
9673
9674audio_patch_handle_t generate_patch_handle()
9675{
9676 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9677 if (++patch_handle < 0)
9678 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9679 return patch_handle;
9680}
9681
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309682int adev_create_audio_patch(struct audio_hw_device *dev,
9683 unsigned int num_sources,
9684 const struct audio_port_config *sources,
9685 unsigned int num_sinks,
9686 const struct audio_port_config *sinks,
9687 audio_patch_handle_t *handle)
9688{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009689 int ret = 0;
9690 struct audio_device *adev = (struct audio_device *)dev;
9691 struct audio_patch_info *p_info = NULL;
9692 patch_type_t patch_type = PATCH_NONE;
9693 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9694 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9695 struct audio_stream_info *s_info = NULL;
9696 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009697 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009698 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9699 bool new_patch = false;
9700 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309701
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009702 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9703 num_sources, num_sinks, *handle);
9704
9705 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9706 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9707 ALOGE("%s: Invalid patch arguments", __func__);
9708 ret = -EINVAL;
9709 goto done;
9710 }
9711
9712 if (num_sources > 1) {
9713 ALOGE("%s: Multiple sources are not supported", __func__);
9714 ret = -EINVAL;
9715 goto done;
9716 }
9717
9718 if (sources == NULL || sinks == NULL) {
9719 ALOGE("%s: Invalid sources or sinks port config", __func__);
9720 ret = -EINVAL;
9721 goto done;
9722 }
9723
9724 ALOGV("%s: source role %d, source type %d", __func__,
9725 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009726 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009727
9728 // Populate source/sink information and fetch stream info
9729 switch (sources[0].type) {
9730 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9731 device_type = sources[0].ext.device.type;
9732 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009733 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009734 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9735 patch_type = PATCH_CAPTURE;
9736 io_handle = sinks[0].ext.mix.handle;
9737 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009738 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009739 __func__, device_type, io_handle);
9740 } else {
9741 // Device to device patch is not implemented.
9742 // This space will need changes if audio HAL
9743 // handles device to device patches in the future.
9744 patch_type = PATCH_DEVICE_LOOPBACK;
9745 }
9746 break;
9747 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9748 io_handle = sources[0].ext.mix.handle;
9749 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009750 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009751 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009752 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009753 }
9754 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009755 ALOGD("%s: Playback patch from mix handle %d to device %x",
9756 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009757 break;
9758 case AUDIO_PORT_TYPE_SESSION:
9759 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009760 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9761 ret = -EINVAL;
9762 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009763 }
9764
9765 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009766
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009767 // Generate patch info and update patch
9768 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009769 *handle = generate_patch_handle();
9770 p_info = (struct audio_patch_info *)
9771 calloc(1, sizeof(struct audio_patch_info));
9772 if (p_info == NULL) {
9773 ALOGE("%s: Failed to allocate memory", __func__);
9774 pthread_mutex_unlock(&adev->lock);
9775 ret = -ENOMEM;
9776 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009777 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009778 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009779 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009780 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009781 if (p_info == NULL) {
9782 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9783 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009784 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009785 ret = -EINVAL;
9786 goto done;
9787 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009788 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009789 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009790 *handle, p_info, patch_type, new_patch);
9791
9792 // Fetch stream info of associated mix for playback or capture patches
9793 if (p_info->patch_type == PATCH_PLAYBACK ||
9794 p_info->patch_type == PATCH_CAPTURE) {
9795 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9796 if (s_info == NULL) {
9797 ALOGE("%s: Failed to obtain stream info", __func__);
9798 if (new_patch)
9799 free(p_info);
9800 pthread_mutex_unlock(&adev->lock);
9801 ret = -EINVAL;
9802 goto done;
9803 }
9804 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9805 s_info->patch_handle = *handle;
9806 stream = s_info->stream;
9807 }
9808 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009809
9810 // Update routing for stream
9811 if (stream != NULL) {
9812 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009813 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009814 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009815 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009816 if (ret < 0) {
9817 pthread_mutex_lock(&adev->lock);
9818 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9819 if (new_patch)
9820 free(p_info);
9821 pthread_mutex_unlock(&adev->lock);
9822 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9823 goto done;
9824 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009825 }
9826
9827 // Add new patch to patch map
9828 if (!ret && new_patch) {
9829 pthread_mutex_lock(&adev->lock);
9830 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009831 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009832 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009833 }
9834
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009835done:
9836 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009837 num_sources,
9838 sources,
9839 num_sinks,
9840 sinks,
9841 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009842 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009843 num_sources,
9844 sources,
9845 num_sinks,
9846 sinks,
9847 handle);
9848 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309849}
9850
9851int adev_release_audio_patch(struct audio_hw_device *dev,
9852 audio_patch_handle_t handle)
9853{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009854 struct audio_device *adev = (struct audio_device *) dev;
9855 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009856 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009857 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -08009858
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009859 if (handle == AUDIO_PATCH_HANDLE_NONE) {
9860 ALOGE("%s: Invalid patch handle %d", __func__, handle);
9861 ret = -EINVAL;
9862 goto done;
9863 }
9864
9865 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009866 pthread_mutex_lock(&adev->lock);
9867 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009868 if (p_info == NULL) {
9869 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009870 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009871 ret = -EINVAL;
9872 goto done;
9873 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009874 struct audio_patch *patch = p_info->patch;
9875 if (patch == NULL) {
9876 ALOGE("%s: Patch not found for 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;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009879 goto done;
9880 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009881 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9882 switch (patch->sources[0].type) {
9883 case AUDIO_PORT_TYPE_MIX:
9884 io_handle = patch->sources[0].ext.mix.handle;
9885 break;
9886 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009887 if (p_info->patch_type == PATCH_CAPTURE)
9888 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009889 break;
9890 case AUDIO_PORT_TYPE_SESSION:
9891 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009892 pthread_mutex_unlock(&adev->lock);
9893 ret = -EINVAL;
9894 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009895 }
9896
9897 // Remove patch and reset patch handle in stream info
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009898 patch_map_remove_l(adev, handle);
9899 if (p_info->patch_type == PATCH_PLAYBACK ||
9900 p_info->patch_type == PATCH_CAPTURE) {
9901 struct audio_stream_info *s_info =
9902 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9903 if (s_info == NULL) {
9904 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
9905 pthread_mutex_unlock(&adev->lock);
9906 goto done;
9907 }
9908 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9909 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009910 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009911 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009912
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009913 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009914 struct listnode devices;
9915 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009916 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009917 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009918 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009919 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009920 }
9921
9922 if (ret < 0)
9923 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9924
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009925done:
9926 audio_extn_hw_loopback_release_audio_patch(dev, handle);
9927 audio_extn_auto_hal_release_audio_patch(dev, handle);
9928
9929 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -08009930 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309931}
9932
9933int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9934{
Derek Chenf13dd492018-11-13 14:53:51 -08009935 int ret = 0;
9936
9937 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9938 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9939 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309940}
9941
9942int adev_set_audio_port_config(struct audio_hw_device *dev,
9943 const struct audio_port_config *config)
9944{
Derek Chenf13dd492018-11-13 14:53:51 -08009945 int ret = 0;
9946
9947 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9948 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9949 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309950}
9951
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009952static int adev_dump(const audio_hw_device_t *device __unused,
9953 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009954{
9955 return 0;
9956}
9957
9958static int adev_close(hw_device_t *device)
9959{
Aalique Grahame22e49102018-12-18 14:23:57 -08009960 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309961 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009962
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309963 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009964 return 0;
9965
9966 pthread_mutex_lock(&adev_init_lock);
9967
9968 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309969 if (audio_extn_spkr_prot_is_enabled())
9970 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +05309971 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309972 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009973 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009974 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009975 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009976 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309977 audio_extn_utils_release_streams_cfg_lists(
9978 &adev->streams_output_cfg_list,
9979 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309980 if (audio_extn_qap_is_enabled())
9981 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309982 if (audio_extn_qaf_is_enabled())
9983 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009984 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009985 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009986 free(adev->snd_dev_ref_cnt);
9987 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009988 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9989 pcm_params_free(adev->use_case_table[i]);
9990 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009991 if (adev->adm_deinit)
9992 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309993 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009994 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309995 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309996 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009997 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309998 if (adev->device_cfg_params) {
9999 free(adev->device_cfg_params);
10000 adev->device_cfg_params = NULL;
10001 }
Derek Chend2530072014-11-24 12:39:14 -080010002 if(adev->ext_hw_plugin)
10003 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010004 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010005 free_map(adev->patch_map);
10006 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010007 free(device);
10008 adev = NULL;
10009 }
10010 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010011 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010012 return 0;
10013}
10014
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010015/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10016 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10017 * just that it _might_ work.
10018 */
10019static int period_size_is_plausible_for_low_latency(int period_size)
10020{
10021 switch (period_size) {
10022 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010023 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010024 case 240:
10025 case 320:
10026 case 480:
10027 return 1;
10028 default:
10029 return 0;
10030 }
10031}
10032
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010033static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10034{
10035 bool is_snd_card_status = false;
10036 bool is_ext_device_status = false;
10037 char value[32];
10038 int card = -1;
10039 card_status_t status;
10040
10041 if (cookie != adev || !parms)
10042 return;
10043
10044 if (!parse_snd_card_status(parms, &card, &status)) {
10045 is_snd_card_status = true;
10046 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10047 is_ext_device_status = true;
10048 } else {
10049 // not a valid event
10050 return;
10051 }
10052
10053 pthread_mutex_lock(&adev->lock);
10054 if (card == adev->snd_card || is_ext_device_status) {
10055 if (is_snd_card_status && adev->card_status != status) {
10056 adev->card_status = status;
10057 platform_snd_card_update(adev->platform, status);
10058 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010059 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010060 if (status == CARD_STATUS_OFFLINE)
10061 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010062 } else if (is_ext_device_status) {
10063 platform_set_parameters(adev->platform, parms);
10064 }
10065 }
10066 pthread_mutex_unlock(&adev->lock);
10067 return;
10068}
10069
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010070/* out and adev lock held */
10071static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10072{
10073 struct audio_usecase *uc_info;
10074 float left_p;
10075 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010076 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010077
10078 uc_info = get_usecase_from_list(adev, out->usecase);
10079 if (uc_info == NULL) {
10080 ALOGE("%s: Could not find the usecase (%d) in the list",
10081 __func__, out->usecase);
10082 return -EINVAL;
10083 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010084 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010085
10086 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10087 out->usecase, use_case_table[out->usecase]);
10088
10089 if (restore) {
10090 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010091 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010092 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010093 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10094 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010095 pthread_mutex_lock(&out->compr_mute_lock);
10096 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010097 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010098 out->a2dp_compress_mute = false;
10099 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10100 }
10101 pthread_mutex_unlock(&out->compr_mute_lock);
10102 }
10103 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010104 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10105 // mute compress stream if suspended
10106 pthread_mutex_lock(&out->compr_mute_lock);
10107 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010108 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010109 assign_devices(&devices, &out->device_list);
10110 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010111 left_p = out->volume_l;
10112 right_p = out->volume_r;
10113 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10114 compress_pause(out->compr);
10115 out_set_compr_volume(&out->stream, (float)0, (float)0);
10116 out->a2dp_compress_mute = true;
10117 select_devices(adev, out->usecase);
10118 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10119 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010120 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010121 out->volume_l = left_p;
10122 out->volume_r = right_p;
10123 }
Zhou Songc576a452019-09-09 14:17:40 +080010124 pthread_mutex_unlock(&out->compr_mute_lock);
10125 } else {
10126 // tear down a2dp path for non offloaded streams
10127 if (audio_extn_a2dp_source_is_suspended())
10128 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010129 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010130 }
10131 ALOGV("%s: exit", __func__);
10132 return 0;
10133}
10134
10135int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10136{
10137 int ret = 0;
10138
10139 lock_output_stream(out);
10140 pthread_mutex_lock(&adev->lock);
10141
10142 ret = check_a2dp_restore_l(adev, out, restore);
10143
10144 pthread_mutex_unlock(&adev->lock);
10145 pthread_mutex_unlock(&out->lock);
10146 return ret;
10147}
10148
Haynes Mathew George01156f92018-04-13 15:29:54 -070010149void adev_on_battery_status_changed(bool charging)
10150{
10151 pthread_mutex_lock(&adev->lock);
10152 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10153 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010154 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010155 pthread_mutex_unlock(&adev->lock);
10156}
10157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010158static int adev_open(const hw_module_t *module, const char *name,
10159 hw_device_t **device)
10160{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010161 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010162 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010163 char mixer_ctl_name[128] = {0};
10164 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010165
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010166 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010167 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10168
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010169 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010170 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010171 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010172 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010173 ALOGD("%s: returning existing instance of adev", __func__);
10174 ALOGD("%s: exit", __func__);
10175 pthread_mutex_unlock(&adev_init_lock);
10176 return 0;
10177 }
10178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010179 adev = calloc(1, sizeof(struct audio_device));
10180
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010181 if (!adev) {
10182 pthread_mutex_unlock(&adev_init_lock);
10183 return -ENOMEM;
10184 }
10185
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010186 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10187
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010188 // register audio ext hidl at the earliest
10189 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010190#ifdef DYNAMIC_LOG_ENABLED
10191 register_for_dynamic_logging("hal");
10192#endif
10193
Derek Chenf939fb72018-11-13 13:34:41 -080010194 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010195 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010196 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10197 maj_version = atoi(value);
10198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010199 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010200 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010201 adev->device.common.module = (struct hw_module_t *)module;
10202 adev->device.common.close = adev_close;
10203
10204 adev->device.init_check = adev_init_check;
10205 adev->device.set_voice_volume = adev_set_voice_volume;
10206 adev->device.set_master_volume = adev_set_master_volume;
10207 adev->device.get_master_volume = adev_get_master_volume;
10208 adev->device.set_master_mute = adev_set_master_mute;
10209 adev->device.get_master_mute = adev_get_master_mute;
10210 adev->device.set_mode = adev_set_mode;
10211 adev->device.set_mic_mute = adev_set_mic_mute;
10212 adev->device.get_mic_mute = adev_get_mic_mute;
10213 adev->device.set_parameters = adev_set_parameters;
10214 adev->device.get_parameters = adev_get_parameters;
10215 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10216 adev->device.open_output_stream = adev_open_output_stream;
10217 adev->device.close_output_stream = adev_close_output_stream;
10218 adev->device.open_input_stream = adev_open_input_stream;
10219 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010220 adev->device.create_audio_patch = adev_create_audio_patch;
10221 adev->device.release_audio_patch = adev_release_audio_patch;
10222 adev->device.get_audio_port = adev_get_audio_port;
10223 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010224 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010225 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010226
10227 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010228 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010229 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010230 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010231 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010232 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010233 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010234 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010235 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010236 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010237 /* Init audio and voice feature */
10238 audio_extn_feature_init();
10239 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010240 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010241 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010242 list_init(&adev->active_inputs_list);
10243 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010244 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010245 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10246 audio_extn_utils_hash_eq);
10247 if (!adev->io_streams_map) {
10248 ALOGE("%s: Could not create io streams map", __func__);
10249 ret = -ENOMEM;
10250 goto adev_open_err;
10251 }
10252 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10253 audio_extn_utils_hash_eq);
10254 if (!adev->patch_map) {
10255 ALOGE("%s: Could not create audio patch map", __func__);
10256 ret = -ENOMEM;
10257 goto adev_open_err;
10258 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010259 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010260 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010261 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010262 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010263 adev->perf_lock_opts[0] = 0x101;
10264 adev->perf_lock_opts[1] = 0x20E;
10265 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010266 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010267 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010268 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010269 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010271 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010272 adev->platform = platform_init(adev);
10273 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010274 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010275 ret = -EINVAL;
10276 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010277 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010278
Aalique Grahame22e49102018-12-18 14:23:57 -080010279 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010280 if (audio_extn_qap_is_enabled()) {
10281 ret = audio_extn_qap_init(adev);
10282 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010283 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010284 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010285 }
10286 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10287 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10288 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010289
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010290 if (audio_extn_qaf_is_enabled()) {
10291 ret = audio_extn_qaf_init(adev);
10292 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010293 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010294 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010295 }
10296
10297 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10298 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10299 }
10300
Derek Chenae7b0342019-02-08 15:17:04 -080010301 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010302 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10303
Eric Laurentc4aef752013-09-12 17:45:53 -070010304 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10305 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10306 if (adev->visualizer_lib == NULL) {
10307 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10308 } else {
10309 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10310 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010311 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010312 "visualizer_hal_start_output");
10313 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010314 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010315 "visualizer_hal_stop_output");
10316 }
10317 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010318 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010319 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010320 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010321 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010322 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010323 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010324
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010325 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10326 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10327 if (adev->offload_effects_lib == NULL) {
10328 ALOGE("%s: DLOPEN failed for %s", __func__,
10329 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10330 } else {
10331 ALOGV("%s: DLOPEN successful for %s", __func__,
10332 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10333 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010334 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010335 "offload_effects_bundle_hal_start_output");
10336 adev->offload_effects_stop_output =
10337 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10338 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010339 adev->offload_effects_set_hpx_state =
10340 (int (*)(bool))dlsym(adev->offload_effects_lib,
10341 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010342 adev->offload_effects_get_parameters =
10343 (void (*)(struct str_parms *, struct str_parms *))
10344 dlsym(adev->offload_effects_lib,
10345 "offload_effects_bundle_get_parameters");
10346 adev->offload_effects_set_parameters =
10347 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10348 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010349 }
10350 }
10351
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010352 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10353 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10354 if (adev->adm_lib == NULL) {
10355 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10356 } else {
10357 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10358 adev->adm_init = (adm_init_t)
10359 dlsym(adev->adm_lib, "adm_init");
10360 adev->adm_deinit = (adm_deinit_t)
10361 dlsym(adev->adm_lib, "adm_deinit");
10362 adev->adm_register_input_stream = (adm_register_input_stream_t)
10363 dlsym(adev->adm_lib, "adm_register_input_stream");
10364 adev->adm_register_output_stream = (adm_register_output_stream_t)
10365 dlsym(adev->adm_lib, "adm_register_output_stream");
10366 adev->adm_deregister_stream = (adm_deregister_stream_t)
10367 dlsym(adev->adm_lib, "adm_deregister_stream");
10368 adev->adm_request_focus = (adm_request_focus_t)
10369 dlsym(adev->adm_lib, "adm_request_focus");
10370 adev->adm_abandon_focus = (adm_abandon_focus_t)
10371 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010372 adev->adm_set_config = (adm_set_config_t)
10373 dlsym(adev->adm_lib, "adm_set_config");
10374 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10375 dlsym(adev->adm_lib, "adm_request_focus_v2");
10376 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10377 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10378 adev->adm_on_routing_change = (adm_on_routing_change_t)
10379 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010380 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10381 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010382 }
10383 }
10384
Aalique Grahame22e49102018-12-18 14:23:57 -080010385 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010386 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010387 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010388 //initialize this to false for now,
10389 //this will be set to true through set param
10390 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010391
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010392 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010393 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010394
10395 if (k_enable_extended_precision)
10396 adev_verify_devices(adev);
10397
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010398 adev->dsp_bit_width_enforce_mode =
10399 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010400
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010401 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10402 &adev->streams_output_cfg_list,
10403 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010404
Kiran Kandi910e1862013-10-29 13:29:42 -070010405 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010406
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010407 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -080010408 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
10409 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010410 trial = atoi(value);
10411 if (period_size_is_plausible_for_low_latency(trial)) {
10412 pcm_config_low_latency.period_size = trial;
10413 pcm_config_low_latency.start_threshold = trial / 4;
10414 pcm_config_low_latency.avail_min = trial / 4;
10415 configured_low_latency_capture_period_size = trial;
10416 }
10417 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010418 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10419 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010420 trial = atoi(value);
10421 if (period_size_is_plausible_for_low_latency(trial)) {
10422 configured_low_latency_capture_period_size = trial;
10423 }
10424 }
10425
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010426 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10427
Eric Laurent4b084132018-10-19 17:33:43 -070010428 adev->camera_orientation = CAMERA_DEFAULT;
10429
Aalique Grahame22e49102018-12-18 14:23:57 -080010430 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
10431 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010432 af_period_multiplier = atoi(value);
10433 if (af_period_multiplier < 0)
10434 af_period_multiplier = 2;
10435 else if (af_period_multiplier > 4)
10436 af_period_multiplier = 4;
10437
10438 ALOGV("new period_multiplier = %d", af_period_multiplier);
10439 }
10440
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010441 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010442
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010443 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Zhou Song62ea0282020-03-22 19:53:01 +080010444 adev->ha_proxy_enable = property_get_bool("persist.vendor.audio.ha_proxy.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010445 pthread_mutex_unlock(&adev_init_lock);
10446
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010447 if (adev->adm_init)
10448 adev->adm_data = adev->adm_init();
10449
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010450 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010451 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010452 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010453
10454 audio_extn_snd_mon_init();
10455 pthread_mutex_lock(&adev->lock);
10456 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10457 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010458 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10459 /*
10460 * if the battery state callback happens before charging can be queried,
10461 * it will be guarded with the adev->lock held in the cb function and so
10462 * the callback value will reflect the latest state
10463 */
10464 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010465 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010466 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010467 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010468 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010469 /* Allocate memory for Device config params */
10470 adev->device_cfg_params = (struct audio_device_config_param*)
10471 calloc(platform_get_max_codec_backend(),
10472 sizeof(struct audio_device_config_param));
10473 if (adev->device_cfg_params == NULL)
10474 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010475
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010476 /*
10477 * Check if new PSPD matrix mixer control is supported. If not
10478 * supported, then set flag so that old mixer ctrl is sent while
10479 * sending pspd coefficients on older kernel version. Query mixer
10480 * control for default pcm id and channel value one.
10481 */
10482 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10483 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10484
10485 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10486 if (!ctl) {
10487 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10488 __func__, mixer_ctl_name);
10489 adev->use_old_pspd_mix_ctrl = true;
10490 }
10491
Eric Laurent994a6932013-07-17 11:51:42 -070010492 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010493 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010494
10495adev_open_err:
10496 free_map(adev->patch_map);
10497 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010498 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010499 pthread_mutex_destroy(&adev->lock);
10500 free(adev);
10501 adev = NULL;
10502 *device = NULL;
10503 pthread_mutex_unlock(&adev_init_lock);
10504 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010505}
10506
10507static struct hw_module_methods_t hal_module_methods = {
10508 .open = adev_open,
10509};
10510
10511struct audio_module HAL_MODULE_INFO_SYM = {
10512 .common = {
10513 .tag = HARDWARE_MODULE_TAG,
10514 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10515 .hal_api_version = HARDWARE_HAL_API_VERSION,
10516 .id = AUDIO_HARDWARE_MODULE_ID,
10517 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010518 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010519 .methods = &hal_module_methods,
10520 },
10521};